@hasna/skills 0.9.7 → 0.9.9
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/README.md +6 -0
- package/bin/index.js +139 -59
- package/bin/mcp.js +1 -1
- package/bin/migrate.js +1 -1
- package/bin/server.js +1 -1
- package/bin/worker.js +1 -1
- package/dist/index.js +1 -1
- package/dist/lib/agent-codex-trust.d.ts +17 -0
- package/dist/lib/codex-hook-rpc.d.ts +1 -1
- package/dist/sdk/index.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -120,6 +120,12 @@ skills hook trust --agent codex --apply --plan-digest <reviewed-plan-digest> --j
|
|
|
120
120
|
|
|
121
121
|
Review the commands, current hashes, and existing trust/enable state in the
|
|
122
122
|
plan. Apply refuses if the plan, package, declarations, or configuration changed.
|
|
123
|
+
The plan preserves the native `CODEX_HOME` choice. When unset, Codex uses
|
|
124
|
+
the lexical `~/.codex` path; an explicit `CODEX_HOME` resolves canonically.
|
|
125
|
+
Only the home root and an explicitly admitted canonical root-alias target
|
|
126
|
+
are accepted. Those views have separate hook identities even when they reach
|
|
127
|
+
the same files; enrolling one preserves the other's trust entries. Keep the
|
|
128
|
+
same `CODEX_HOME` choice for enrollment and the consuming agent.
|
|
123
129
|
It enrolls the current exact definitions, including reviewed modified hooks,
|
|
124
130
|
and preserves unrelated trust, settings, and comments. A private journal keeps
|
|
125
131
|
the pre-write configuration; a failed write or verification requires journal
|
package/bin/index.js
CHANGED
|
@@ -36868,7 +36868,7 @@ var package_default;
|
|
|
36868
36868
|
var init_package = __esm(() => {
|
|
36869
36869
|
package_default = {
|
|
36870
36870
|
name: "@hasna/skills",
|
|
36871
|
-
version: "0.9.
|
|
36871
|
+
version: "0.9.9",
|
|
36872
36872
|
description: "Skills library for AI coding agents",
|
|
36873
36873
|
type: "module",
|
|
36874
36874
|
bin: {
|
|
@@ -107920,9 +107920,14 @@ async function connectCodexHookRpc(options) {
|
|
|
107920
107920
|
const current = statSync20(binary);
|
|
107921
107921
|
if (realpathSync11(found) !== binary || ["dev", "ino", "size", "mtimeMs", "ctimeMs"].some((k) => stat3[k] !== current[k]))
|
|
107922
107922
|
throw new Error("CODEX_HOOK_TRUST_NATIVE_EXECUTABLE_CHANGED");
|
|
107923
|
+
const env3 = { ...process.env, HOME: options.home, NO_COLOR: "1" };
|
|
107924
|
+
if (options.codexHome === undefined)
|
|
107925
|
+
delete env3.CODEX_HOME;
|
|
107926
|
+
else
|
|
107927
|
+
env3.CODEX_HOME = options.codexHome;
|
|
107923
107928
|
const child = spawn3(binary, ["app-server", "--strict-config", "--stdio"], {
|
|
107924
107929
|
cwd: options.home,
|
|
107925
|
-
env:
|
|
107930
|
+
env: env3,
|
|
107926
107931
|
stdio: ["pipe", "pipe", "pipe"]
|
|
107927
107932
|
});
|
|
107928
107933
|
const pending = new Map;
|
|
@@ -108256,11 +108261,33 @@ var init_codex_hook_trust_identity = __esm(() => {
|
|
|
108256
108261
|
});
|
|
108257
108262
|
|
|
108258
108263
|
// src/lib/agent-codex-trust.ts
|
|
108259
|
-
import { lstatSync as lstatSync28, mkdirSync as mkdirSync25, readdirSync as readdirSync20 } from "fs";
|
|
108264
|
+
import { lstatSync as lstatSync28, mkdirSync as mkdirSync25, readdirSync as readdirSync20, readFileSync as readFileSync37, realpathSync as realpathSync13, statSync as statSync21 } from "fs";
|
|
108260
108265
|
import { createHash as createHash26, randomUUID as randomUUID10 } from "crypto";
|
|
108261
|
-
import {
|
|
108266
|
+
import { execFileSync } from "child_process";
|
|
108267
|
+
import { dirname as dirname30, isAbsolute as isAbsolute25, join as join56, resolve as resolve22 } from "path";
|
|
108262
108268
|
import { homedir as homedir11 } from "os";
|
|
108263
108269
|
import { isDeepStrictEqual as isDeepStrictEqual6 } from "util";
|
|
108270
|
+
function verifyReleaseArtifact(proof, skillsCli) {
|
|
108271
|
+
need4(isAbsolute25(proof.packageTarPath) && !proof.packageTarPath.includes("\x00"), "RECONCILE_RELEASE_PROVENANCE_PATH");
|
|
108272
|
+
const tarPath = realpathSync13(proof.packageTarPath);
|
|
108273
|
+
need4(statSync21(tarPath).isFile(), "RECONCILE_RELEASE_PROVENANCE_PATH");
|
|
108274
|
+
const tarBytes = readFileSync37(tarPath);
|
|
108275
|
+
need4(tarBytes.byteLength === proof.packageTarBytes && createHash26("sha256").update(tarBytes).digest("hex") === proof.packageTarSha256, "RECONCILE_RELEASE_ARTIFACT_CHANGED");
|
|
108276
|
+
const packageRoot = dirname30(dirname30(realpathSync13(skillsCli.receipt.path)));
|
|
108277
|
+
const manifest = readFileSync37(join56(packageRoot, "package.json"));
|
|
108278
|
+
need4(createHash26("sha256").update(manifest).digest("hex") === skillsCli.receipt.manifestSha256 && skillsCli.receipt.manifestSha256 === proof.manifestSha256, "RECONCILE_RELEASE_MANIFEST_CHANGED");
|
|
108279
|
+
need4(createHash26("sha256").update(readFileSync37(skillsCli.receipt.path)).digest("hex") === proof.executableSha256 && skillsCli.receipt.sha256 === proof.executableSha256, "RECONCILE_RELEASE_EXECUTABLE_CHANGED");
|
|
108280
|
+
const members2 = [["package/package.json", manifest], ["package/bin/index.js", readFileSync37(skillsCli.receipt.path)]];
|
|
108281
|
+
for (const [member, expected] of members2) {
|
|
108282
|
+
let actual;
|
|
108283
|
+
try {
|
|
108284
|
+
actual = execFileSync("tar", ["-xOf", tarPath, member], { maxBuffer: 32 * 1024 * 1024 });
|
|
108285
|
+
} catch {
|
|
108286
|
+
throw new Error("RECONCILE_RELEASE_ARTIFACT_MEMBER_MISSING");
|
|
108287
|
+
}
|
|
108288
|
+
need4(Buffer.compare(actual, expected) === 0, "RECONCILE_RELEASE_ARTIFACT_MEMBER_CHANGED");
|
|
108289
|
+
}
|
|
108290
|
+
}
|
|
108264
108291
|
async function reconcileCodexNativeHooks(options, connect = connectCodexHookRpc) {
|
|
108265
108292
|
let rpc;
|
|
108266
108293
|
try {
|
|
@@ -108279,30 +108306,61 @@ async function reconcileCodexNativeHooks(options, connect = connectCodexHookRpc)
|
|
|
108279
108306
|
const declarations = intent.declarations ?? intent.hooks.map((hook) => ({ event: hook.event, key: `${join56(home, ".codex/hooks.json")}${hook.key.slice(hook.key.indexOf(".codex/hooks.json") + ".codex/hooks.json".length)}`, command: hook.command }));
|
|
108280
108307
|
const admitted = intent.admitted ?? intent.hooks;
|
|
108281
108308
|
const configSha256 = intent.configSha256 ?? configBefore.sha256, configVersion = intent.configVersion ?? intent.expectedVersion;
|
|
108282
|
-
const digestInput = { version: 1, home: intent.home ?? home, configPath: intent.configPath, configSha256, configVersion, policySha256: intent.policySha256, hooksSha256: intent.hooksSha256, skillsCli: intent.skillsCli, nativeVersion: intent.nativeVersion, declarations, admitted };
|
|
108309
|
+
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 };
|
|
108283
108310
|
need4(makePlanDigest(digestInput) === intent.planDigest, "RECONCILE_PLAN_CHANGED");
|
|
108284
108311
|
need4(isDeepStrictEqual6(intent.hooks, admitted.filter((hook) => !hook.enabled || hook.trustStatus !== "trusted")), "RECONCILE_INTENT_HOOKS_CHANGED");
|
|
108285
|
-
need4(configBefore.sha256 === intent.beforeSha256 && hooksBefore.sha256 === intent.hooksSha256 && policyBefore.sha256 === intent.policySha256, "RECONCILE_JOURNAL_CHANGED");
|
|
108312
|
+
need4(configBefore.sha256 === (intent.beforeSha256 ?? intent.configSha256) && hooksBefore.sha256 === intent.hooksSha256 && policyBefore.sha256 === intent.policySha256, "RECONCILE_JOURNAL_CHANGED");
|
|
108313
|
+
const policyCurrent = snapshot(join56(dataDir3, "agent-policy.json"), true);
|
|
108314
|
+
let supersededBinding = false;
|
|
108315
|
+
if (policyCurrent.sha256 !== policyBefore.sha256) {
|
|
108316
|
+
need4(options.supersedeBinding === true, "RECONCILE_POLICY_CHANGED");
|
|
108317
|
+
const oldPolicy = JSON.parse(policyBefore.text), currentPolicy = JSON.parse(policyCurrent.text);
|
|
108318
|
+
need4(isDeepStrictEqual6(withoutCodexCommand(oldPolicy), withoutCodexCommand(currentPolicy)), "RECONCILE_POLICY_CHANGED");
|
|
108319
|
+
supersededBinding = true;
|
|
108320
|
+
}
|
|
108321
|
+
if (supersededBinding) {
|
|
108322
|
+
need4(Array.isArray(intent.nativeHooks) && intent.nativeHooks.length > 0, "RECONCILE_NATIVE_INVENTORY_REQUIRED");
|
|
108323
|
+
const proof = options.releaseProof;
|
|
108324
|
+
need4(!!proof && isAbsolute25(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");
|
|
108325
|
+
}
|
|
108286
108326
|
const currentConfig = snapshot(intent.configPath, true);
|
|
108287
108327
|
const managedKeys = intent.hooks.map((h) => h.key);
|
|
108288
|
-
|
|
108289
|
-
|
|
108328
|
+
const witnessSame = codexTrustReconcileWitness(configBefore.text, managedKeys) === codexTrustReconcileWitness(currentConfig.text, managedKeys);
|
|
108329
|
+
const unmanagedSame = codexTrustUnmanagedSemantic(configBefore.text, managedKeys) === codexTrustUnmanagedSemantic(currentConfig.text, managedKeys);
|
|
108330
|
+
need4(unmanagedSame && (witnessSame || supersededBinding), "RECONCILE_UNRELATED_CONFIG_CHANGED");
|
|
108290
108331
|
const before2 = structure(configBefore.text), current = structure(currentConfig.text), expectedConfig = structuredClone(before2);
|
|
108291
108332
|
expectedConfig.hooks ??= {};
|
|
108292
108333
|
expectedConfig.hooks.state ??= {};
|
|
108293
108334
|
for (const hook of intent.hooks)
|
|
108294
108335
|
expectedConfig.hooks.state[hook.key] = { ...expectedConfig.hooks.state[hook.key], enabled: true, trusted_hash: hook.currentHash };
|
|
108295
|
-
|
|
108296
|
-
|
|
108297
|
-
|
|
108298
|
-
|
|
108336
|
+
if (supersededBinding) {
|
|
108337
|
+
for (const hook of intent.hooks) {
|
|
108338
|
+
const state = current.hooks?.state?.[hook.key];
|
|
108339
|
+
need4(state?.enabled === true && typeof state.trusted_hash === "string" && /^sha256:[a-f0-9]{64}$/.test(state.trusted_hash), "RECONCILE_CONFIG_DRIFT");
|
|
108340
|
+
}
|
|
108341
|
+
} else
|
|
108342
|
+
need4(isDeepStrictEqual6(expectedConfig, current), "RECONCILE_CONFIG_DRIFT");
|
|
108343
|
+
const policy = parseManagedSkillPolicy(policyCurrent.text), binding = policy.bridge;
|
|
108299
108344
|
assertManagedAgentBridge("codex", { home, dataDir: dataDir3, projectDir: home });
|
|
108300
108345
|
const skillsCli = bindSkillsCli(binding.commands.codex, options.reviewedSkillsCli);
|
|
108301
|
-
|
|
108302
|
-
|
|
108303
|
-
|
|
108346
|
+
if (supersededBinding)
|
|
108347
|
+
verifyReleaseArtifact(options.releaseProof, skillsCli);
|
|
108348
|
+
const skillsBindingChanged = !isDeepStrictEqual6(skillsCli.receipt, intent.skillsCli);
|
|
108349
|
+
need4(!skillsBindingChanged || supersededBinding, "RECONCILE_SKILLS_BINDING_CHANGED");
|
|
108350
|
+
const alias = binding.rootAliases?.find((item) => item.agent === "codex"), physicalRoot = alias?.target ?? join56(home, ".codex"), hooksPath = join56(physicalRoot, "hooks.json");
|
|
108351
|
+
need4(resolve22(intent.configPath) === resolve22(join56(physicalRoot, "config.toml")), "RECONCILE_CONFIG_PATH_CHANGED");
|
|
108352
|
+
const nativeConfigPath = intent.nativeConfigPath ?? intent.configPath;
|
|
108353
|
+
need4([join56(home, ".codex/config.toml"), join56(physicalRoot, "config.toml")].includes(nativeConfigPath), "RECONCILE_NATIVE_CONFIG_PATH_CHANGED");
|
|
108354
|
+
const codexHome = nativeConfigPath !== intent.configPath ? undefined : dirname30(nativeConfigPath);
|
|
108304
108355
|
const hooksCurrent = snapshot(hooksPath);
|
|
108305
|
-
|
|
108356
|
+
if (hooksCurrent.sha256 !== intent.hooksSha256 && hooksCurrent.sha256 !== hooksBefore.sha256) {
|
|
108357
|
+
need4(supersededBinding, "RECONCILE_HOOKS_CHANGED");
|
|
108358
|
+
const currentDeclarations = JSON.parse(hooksCurrent.text).hooks;
|
|
108359
|
+
for (const [event, [nativeEvent]] of Object.entries(eventNames)) {
|
|
108360
|
+
const command = renderAgentHookCommand(binding.commands.codex, "codex", binding.profiles.codex, event);
|
|
108361
|
+
need4(isDeepStrictEqual6(currentDeclarations?.[event], [{ hooks: [{ type: "command", command, timeout: 15 }] }]), "RECONCILE_BINDING_HOOK_CHANGED");
|
|
108362
|
+
}
|
|
108363
|
+
}
|
|
108306
108364
|
rpc = await connect({ command: options.codexCommand ?? "codex", home, codexHome });
|
|
108307
108365
|
need4(rpc.version === intent.nativeVersion, "RECONCILE_NATIVE_VERSION_CHANGED");
|
|
108308
108366
|
const discovered = await rpc.request("hooks/list", { cwds: [home] });
|
|
@@ -108312,12 +108370,15 @@ async function reconcileCodexNativeHooks(options, connect = connectCodexHookRpc)
|
|
|
108312
108370
|
if (recordedNativeHooks)
|
|
108313
108371
|
need4(nativeHooks.length === recordedNativeHooks.length, "RECONCILE_NATIVE_HOOK_LIST_CHANGED");
|
|
108314
108372
|
const plannedKeys = new Set(intent.hooks.map((hook) => hook.key));
|
|
108373
|
+
let nativeTrustPending = false;
|
|
108315
108374
|
for (const expected of recordedNativeHooks ?? []) {
|
|
108316
108375
|
const matches2 = nativeHooks.filter((hook) => hook.key === expected.key);
|
|
108317
108376
|
need4(matches2.length === 1, "RECONCILE_NATIVE_HOOK_LIST_CHANGED");
|
|
108318
108377
|
const actual = safeNativeHook(matches2[0]);
|
|
108319
108378
|
const stable = (hook) => {
|
|
108320
108379
|
const { enabled, trustStatus, ...identity4 } = hook;
|
|
108380
|
+
if (supersededBinding)
|
|
108381
|
+
delete identity4.command;
|
|
108321
108382
|
return identity4;
|
|
108322
108383
|
};
|
|
108323
108384
|
need4(isDeepStrictEqual6(stable(actual), stable(expected)), "RECONCILE_NATIVE_IDENTITY_CHANGED");
|
|
@@ -108328,15 +108389,22 @@ async function reconcileCodexNativeHooks(options, connect = connectCodexHookRpc)
|
|
|
108328
108389
|
const matches2 = nativeHooks.filter((h2) => h2.key === wanted.key || h2.key === wanted.key.replace(join56(home, ".codex/hooks.json"), hooksPath));
|
|
108329
108390
|
need4(matches2.length === 1, "RECONCILE_NATIVE_IDENTITY_CHANGED");
|
|
108330
108391
|
const h = matches2[0];
|
|
108331
|
-
|
|
108392
|
+
const trusted = h.trustStatus === "trusted";
|
|
108393
|
+
need4(h.enabled === true && (trusted || supersededBinding && h.trustStatus === "modified") && (h.currentHash === wanted.currentHash || supersededBinding && /^sha256:[a-f0-9]{64}$/.test(h.currentHash)), "RECONCILE_NATIVE_STATE_INCOMPLETE");
|
|
108394
|
+
if (!trusted)
|
|
108395
|
+
nativeTrustPending = true;
|
|
108396
|
+
if (supersededBinding) {
|
|
108397
|
+
const nativeToCliEvent = { userPromptSubmit: "UserPromptSubmit", sessionStart: "SessionStart", subagentStart: "SubagentStart" };
|
|
108398
|
+
need4(h.command === renderAgentHookCommand(binding.commands.codex, "codex", binding.profiles.codex, nativeToCliEvent[wanted.event] ?? ""), "RECONCILE_BINDING_HOOK_CHANGED");
|
|
108399
|
+
}
|
|
108332
108400
|
}
|
|
108333
108401
|
const config2 = await rpc.request("config/read", { includeLayers: true, cwd: home });
|
|
108334
|
-
const layers = config2?.layers?.filter((layer) => layer.name?.type === "user" && layer.name.file ===
|
|
108402
|
+
const layers = config2?.layers?.filter((layer) => layer.name?.type === "user" && layer.name.file === nativeConfigPath && !layer.name.profile);
|
|
108335
108403
|
need4(layers?.length === 1 && !layers[0].disabledReason && isDeepStrictEqual6(layers[0].config, current), "RECONCILE_NATIVE_CONFIG_MISMATCH");
|
|
108336
108404
|
const finalDiscovery = await rpc.request("hooks/list", { cwds: [home] });
|
|
108337
108405
|
need4(Array.isArray(finalDiscovery?.data) && finalDiscovery.data.length === 1 && finalDiscovery.data[0].cwd === home && !finalDiscovery.data[0].errors?.length && !finalDiscovery.data[0].warnings?.length && (!recordedNativeHooks || isDeepStrictEqual6(finalDiscovery.data[0].hooks.map(safeNativeHook), nativeHooks.map(safeNativeHook))), "RECONCILE_NATIVE_STATE_CHANGED");
|
|
108338
108406
|
const finalConfig = await rpc.request("config/read", { includeLayers: true, cwd: home });
|
|
108339
|
-
const finalLayers = finalConfig?.layers?.filter((layer) => layer.name?.type === "user" && layer.name.file ===
|
|
108407
|
+
const finalLayers = finalConfig?.layers?.filter((layer) => layer.name?.type === "user" && layer.name.file === nativeConfigPath && !layer.name.profile);
|
|
108340
108408
|
need4(finalLayers?.length === 1 && isDeepStrictEqual6(finalLayers[0].config, current), "RECONCILE_NATIVE_CONFIG_CHANGED");
|
|
108341
108409
|
unchanged2(stoppedFile);
|
|
108342
108410
|
unchanged2(intentFile);
|
|
@@ -108348,7 +108416,7 @@ async function reconcileCodexNativeHooks(options, connect = connectCodexHookRpc)
|
|
|
108348
108416
|
unchanged2(currentConfig);
|
|
108349
108417
|
skillsCli.recheck();
|
|
108350
108418
|
assertManagedAgentBridge("codex", { home, dataDir: dataDir3, projectDir: home });
|
|
108351
|
-
const receipt = { version: 1, status: "reconciled", reconciled: true, automaticRollback: false, journal, planDigest: intent.planDigest, nativeVersion: rpc.version, nativeStateVerified:
|
|
108419
|
+
const receipt = { version: 1, status: supersededBinding ? "superseded" : "reconciled", reconciled: true, supersededBinding, automaticRollback: false, journal, planDigest: intent.planDigest, nativeVersion: rpc.version, nativeStateVerified: !nativeTrustPending, nativeTrustPending, 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 };
|
|
108352
108420
|
save2(join56(journal, "receipt.json"), json2(receipt));
|
|
108353
108421
|
return receipt;
|
|
108354
108422
|
} catch (error61) {
|
|
@@ -108366,7 +108434,10 @@ async function enrollCodexNativeHooks(options = {}, connect = connectCodexHookRp
|
|
|
108366
108434
|
const policyFile = snapshot(join56(dataDir3, "agent-policy.json"), true), policy = parseManagedSkillPolicy(policyFile.text);
|
|
108367
108435
|
const binding = policy.bridge, alias = binding.rootAliases?.find((item) => item.agent === "codex");
|
|
108368
108436
|
const skillsCli = bindSkillsCli(binding.commands.codex, options.reviewedSkillsCli);
|
|
108369
|
-
const
|
|
108437
|
+
const physicalRoot = alias?.target ?? join56(home, ".codex"), hooksPath = join56(physicalRoot, "hooks.json"), configPath = join56(physicalRoot, "config.toml");
|
|
108438
|
+
need4(options.codexHome === undefined || isAbsolute25(options.codexHome) && [join56(home, ".codex"), physicalRoot].includes(options.codexHome), "NATIVE_HOME_NOT_ADMITTED");
|
|
108439
|
+
const codexHome = options.codexHome === undefined ? undefined : physicalRoot;
|
|
108440
|
+
const nativeConfigPath = join56(codexHome ?? join56(home, ".codex"), "config.toml");
|
|
108370
108441
|
const hooksFile = snapshot(hooksPath), configFile = snapshot(configPath, true), original = structure(configFile.text);
|
|
108371
108442
|
const declarations = JSON.parse(hooksFile.text).hooks, expected = [];
|
|
108372
108443
|
for (const [event, [nativeEvent, label]] of Object.entries(eventNames)) {
|
|
@@ -108397,7 +108468,7 @@ async function enrollCodexNativeHooks(options = {}, connect = connectCodexHookRp
|
|
|
108397
108468
|
});
|
|
108398
108469
|
const discovered = await list2(), admitted = admit(discovered);
|
|
108399
108470
|
const config2 = await rpc.request("config/read", { includeLayers: true, cwd: home });
|
|
108400
|
-
const layers = config2?.layers?.filter((layer) => layer.name?.type === "user" && layer.name.file ===
|
|
108471
|
+
const layers = config2?.layers?.filter((layer) => layer.name?.type === "user" && layer.name.file === nativeConfigPath && !layer.name.profile);
|
|
108401
108472
|
need4(layers?.length === 1 && /^sha256:[a-f0-9]{64}$/.test(layers[0].version) && !layers[0].disabledReason && isDeepStrictEqual6(layers[0].config, original), "NATIVE_CONFIG_MISMATCH");
|
|
108402
108473
|
need4(config2.config && config2.config.features?.hooks !== false, "NATIVE_HOOKS_DISABLED");
|
|
108403
108474
|
need4(config2.layers.slice(0, config2.layers.indexOf(layers[0])).every((layer) => layer.config?.hooks === undefined && layer.config?.features?.hooks === undefined), "NATIVE_CONFIG_OVERRIDDEN");
|
|
@@ -108411,9 +108482,9 @@ async function enrollCodexNativeHooks(options = {}, connect = connectCodexHookRp
|
|
|
108411
108482
|
unchanged2(configFile);
|
|
108412
108483
|
};
|
|
108413
108484
|
checkInputs();
|
|
108414
|
-
const digestInput = { version: 1, home, configPath, configSha256: configFile.sha256, configVersion: layers[0].version, policySha256: policyFile.sha256, hooksSha256: hooksFile.sha256, skillsCli: skillsCli.receipt, nativeVersion: rpc.version, declarations: expected, admitted };
|
|
108485
|
+
const digestInput = { version: 1, home, configPath, ...nativeConfigPath !== configPath ? { nativeConfigPath } : {}, configSha256: configFile.sha256, configVersion: layers[0].version, policySha256: policyFile.sha256, hooksSha256: hooksFile.sha256, skillsCli: skillsCli.receipt, nativeVersion: rpc.version, declarations: expected, admitted };
|
|
108415
108486
|
const planDigest = makePlanDigest(digestInput);
|
|
108416
|
-
const baseReceipt = { planDigest, skillsCli: skillsCli.receipt, nativeVersion: rpc.version, ownedNativeProcessId: rpc.processId, agent: "codex", applied: false, planned, nativeEligible: planned.length === 0, transport: "owned-stdio-process", existingSessionsReloaded: false, nativeExecutionVerified: false };
|
|
108487
|
+
const baseReceipt = { planDigest, skillsCli: skillsCli.receipt, nativeVersion: rpc.version, nativeConfigPath, ownedNativeProcessId: rpc.processId, agent: "codex", applied: false, planned, nativeEligible: planned.length === 0, transport: "owned-stdio-process", existingSessionsReloaded: false, nativeExecutionVerified: false };
|
|
108417
108488
|
if (options.apply)
|
|
108418
108489
|
need4(options.reviewedPlanDigest === planDigest, "PLAN_CHANGED: run the dry-run again and pass its reviewed --plan-digest with --apply");
|
|
108419
108490
|
const parent = join56(dataDir3, "native-hook-trust");
|
|
@@ -108478,7 +108549,12 @@ async function enrollCodexNativeHooks(options = {}, connect = connectCodexHookRp
|
|
|
108478
108549
|
}
|
|
108479
108550
|
}
|
|
108480
108551
|
var json2 = (value) => JSON.stringify(value, null, 2) + `
|
|
108481
|
-
`, structure = (text3) => JSON.parse(JSON.stringify(Bun.TOML.parse(text3))), eventNames, makePlanDigest = (value) => createHash26("sha256").update(json2(value)).digest("hex"), safeNativeHook = (hook) => ({ key: hook.key, eventName: hook.eventName, handlerType: hook.handlerType, command: hook.command, matcher: hook.matcher, timeoutSec: hook.timeoutSec, async: hook.async, statusMessage: hook.statusMessage, additionalContextLimit: hook.additionalContextLimit, sourcePath: hook.sourcePath, source: hook.source, pluginId: hook.pluginId, isManaged: hook.isManaged, currentHash: hook.currentHash, enabled: hook.enabled, trustStatus: hook.trustStatus })
|
|
108552
|
+
`, structure = (text3) => JSON.parse(JSON.stringify(Bun.TOML.parse(text3))), eventNames, makePlanDigest = (value) => createHash26("sha256").update(json2(value)).digest("hex"), safeNativeHook = (hook) => ({ key: hook.key, eventName: hook.eventName, handlerType: hook.handlerType, command: hook.command, matcher: hook.matcher, timeoutSec: hook.timeoutSec, async: hook.async, statusMessage: hook.statusMessage, additionalContextLimit: hook.additionalContextLimit, sourcePath: hook.sourcePath, source: hook.source, pluginId: hook.pluginId, isManaged: hook.isManaged, currentHash: hook.currentHash, enabled: hook.enabled, trustStatus: hook.trustStatus }), withoutCodexCommand = (value) => {
|
|
108553
|
+
const copy = structuredClone(value);
|
|
108554
|
+
if (copy?.bridge?.commands && Object.hasOwn(copy.bridge.commands, "codex"))
|
|
108555
|
+
copy.bridge.commands.codex = "<reviewed-codex-binding>";
|
|
108556
|
+
return copy;
|
|
108557
|
+
};
|
|
108482
108558
|
var init_agent_codex_trust = __esm(() => {
|
|
108483
108559
|
init_config();
|
|
108484
108560
|
init_managed_policy();
|
|
@@ -108571,8 +108647,8 @@ var exports_agent_integration = {};
|
|
|
108571
108647
|
__export(exports_agent_integration, {
|
|
108572
108648
|
registerAgentIntegration: () => registerAgentIntegration
|
|
108573
108649
|
});
|
|
108574
|
-
import { readFileSync as
|
|
108575
|
-
import { isAbsolute as
|
|
108650
|
+
import { readFileSync as readFileSync38 } from "fs";
|
|
108651
|
+
import { isAbsolute as isAbsolute26 } from "path";
|
|
108576
108652
|
function pinnedHookProfile(input3, configuredProfile) {
|
|
108577
108653
|
try {
|
|
108578
108654
|
const parsed = parseSkillContextInput(JSON.stringify(input3));
|
|
@@ -108643,7 +108719,7 @@ function registerAgentIntegration(parent) {
|
|
|
108643
108719
|
});
|
|
108644
108720
|
hook.command("install").option("--agent <agent>", `Agent to configure: ${INTEGRATION_AGENTS.join(", ")}, all`, "all").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("--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) => {
|
|
108645
108721
|
try {
|
|
108646
|
-
const discoveryInputs = options.discoveryInputs ? JSON.parse(
|
|
108722
|
+
const discoveryInputs = options.discoveryInputs ? JSON.parse(readFileSync38(options.discoveryInputs, "utf8")) : undefined;
|
|
108647
108723
|
const plan = planAgentIntegration({ agents: agents(options.agent), command: options.command, profileId: options.selectionProfile, includeVendor: options.includeVendor, discoveryInputs, allowRootAliases: options.allowRootAliases });
|
|
108648
108724
|
const result2 = options.apply ? applyAgentIntegration(plan) : { changed: [], backups: [] };
|
|
108649
108725
|
const receipt = { 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) };
|
|
@@ -108662,7 +108738,7 @@ function registerAgentIntegration(parent) {
|
|
|
108662
108738
|
throw new Error("Native trust enrollment requires --agent codex");
|
|
108663
108739
|
if (options.agent !== "codex")
|
|
108664
108740
|
throw new Error("Native trust enrollment currently supports --agent codex only");
|
|
108665
|
-
const result2 = await enrollCodexNativeHooks({ codexCommand: options.codexCommand, apply: options.apply, reviewedPlanDigest: options.planDigest });
|
|
108741
|
+
const result2 = await enrollCodexNativeHooks({ codexCommand: options.codexCommand, codexHome: process.env.CODEX_HOME, apply: options.apply, reviewedPlanDigest: options.planDigest });
|
|
108666
108742
|
if (options.json)
|
|
108667
108743
|
await writeCliOutput(JSON.stringify(result2));
|
|
108668
108744
|
else
|
|
@@ -108672,11 +108748,15 @@ function registerAgentIntegration(parent) {
|
|
|
108672
108748
|
process.exitCode = 1;
|
|
108673
108749
|
}
|
|
108674
108750
|
});
|
|
108675
|
-
trust.command("reconcile").requiredOption("--agent <agent>", "Native trust adapter (codex)").requiredOption("--journal <path>", "Private incomplete native trust journal to inspect").option("--codex-command <path>", "Installed Codex executable used for its native configuration API", "codex").option("--json", "Output the reconciliation receipt", false).description("Verify an interrupted Codex native trust write and resolve its private journal").action(async (options) => {
|
|
108751
|
+
trust.command("reconcile").requiredOption("--agent <agent>", "Native trust adapter (codex)").requiredOption("--journal <path>", "Private incomplete native trust journal to inspect").option("--codex-command <path>", "Installed Codex executable used for its native configuration API", "codex").option("--supersede-binding", "Resolve a stale journal only when current policy differs solely by the reviewed Codex CLI binding", false).option("--skills-package-tar <path>", "Exact package tarball consumed by the reviewed executable").option("--skills-package-tar-sha256 <sha256>", "SHA-256 of the reviewed Skills package tarball").option("--skills-package-tar-bytes <bytes>", "Byte length of the reviewed Skills package tarball").option("--skills-package-manifest-sha256 <sha256>", "SHA-256 of the reviewed Skills package manifest").option("--skills-executable-sha256 <sha256>", "SHA-256 of the reviewed running Skills executable").option("--json", "Output the reconciliation receipt", false).description("Verify an interrupted Codex native trust write and resolve its private journal").action(async (options) => {
|
|
108676
108752
|
try {
|
|
108677
108753
|
if (options.agent !== "codex")
|
|
108678
108754
|
throw new Error("Native trust reconciliation currently supports --agent codex only");
|
|
108679
|
-
const
|
|
108755
|
+
const proofFields = [options.skillsPackageTar, options.skillsPackageTarSha256, options.skillsPackageTarBytes, options.skillsPackageManifestSha256, options.skillsExecutableSha256];
|
|
108756
|
+
if (proofFields.some((value) => value !== undefined) && proofFields.some((value) => value === undefined))
|
|
108757
|
+
throw new Error("Release provenance requires package tar path, tar hash/bytes, manifest hash, and executable hash together");
|
|
108758
|
+
const releaseProof = proofFields.every((value) => value !== undefined) ? { packageTarPath: options.skillsPackageTar, packageTarSha256: options.skillsPackageTarSha256, packageTarBytes: Number(options.skillsPackageTarBytes), manifestSha256: options.skillsPackageManifestSha256, executableSha256: options.skillsExecutableSha256 } : undefined;
|
|
108759
|
+
const result2 = await reconcileCodexNativeHooks({ journal: options.journal, codexCommand: options.codexCommand, supersedeBinding: options.supersedeBinding, releaseProof });
|
|
108680
108760
|
if (options.json)
|
|
108681
108761
|
await writeCliOutput(JSON.stringify(result2));
|
|
108682
108762
|
else
|
|
@@ -108693,7 +108773,7 @@ function registerAgentIntegration(parent) {
|
|
|
108693
108773
|
try {
|
|
108694
108774
|
if (agents(options.agent).length !== 1)
|
|
108695
108775
|
throw new Error("A hook invocation requires one agent");
|
|
108696
|
-
const inputText =
|
|
108776
|
+
const inputText = readFileSync38(0, "utf8");
|
|
108697
108777
|
if (inputText.length > 1024 * 1024)
|
|
108698
108778
|
throw new Error("Hook input is too large");
|
|
108699
108779
|
let input3 = JSON.parse(inputText);
|
|
@@ -108706,12 +108786,12 @@ function registerAgentIntegration(parent) {
|
|
|
108706
108786
|
input3.hook_event_name = event;
|
|
108707
108787
|
const projects = [process.cwd()];
|
|
108708
108788
|
if (input3.cwd !== undefined) {
|
|
108709
|
-
if (typeof input3.cwd !== "string" || !
|
|
108789
|
+
if (typeof input3.cwd !== "string" || !isAbsolute26(input3.cwd) || input3.cwd.includes("\x00"))
|
|
108710
108790
|
throw new Error("Invalid native hook working directory");
|
|
108711
108791
|
projects.push(input3.cwd);
|
|
108712
108792
|
}
|
|
108713
108793
|
if (options.agent === "cursor") {
|
|
108714
|
-
if (!Array.isArray(input3.workspace_roots) || input3.workspace_roots.length > 32 || input3.workspace_roots.some((path) => typeof path !== "string" || !
|
|
108794
|
+
if (!Array.isArray(input3.workspace_roots) || input3.workspace_roots.length > 32 || input3.workspace_roots.some((path) => typeof path !== "string" || !isAbsolute26(path) || path.includes("\x00")))
|
|
108715
108795
|
throw new Error("Invalid Cursor workspace roots");
|
|
108716
108796
|
projects.push(...input3.workspace_roots);
|
|
108717
108797
|
input3.cwd ??= input3.workspace_roots[0] ?? process.cwd();
|
|
@@ -108789,7 +108869,7 @@ function registerAgentIntegration(parent) {
|
|
|
108789
108869
|
const migrate = parent.command("migrate").description("Preserve and retire native agent skill copies");
|
|
108790
108870
|
migrate.command("native").option("--project <directory>", "Also inventory a project and its ancestors (the current directory and its ancestors are always included)").option("--include-unmanaged", "Archive user-authored skills as well as Skills-managed copies", false).option("--include-vendor", "Retire vendor SKILL.md discovery files while preserving plugin scripts and assets", false).option("--target-manifest <file>", "Reviewed exact native migration target manifest").option("--discovery-inputs <file>", "Advanced reviewed active plugin roots and source hashes").option("--allow-root-aliases", "Allow home .claude/.codex aliases to existing directories within this home", false).option("--apply", "Move selected skills to private archives outside agent discovery roots", false).option("--json", "Output inventory and archive receipt as JSON", false).description("Inventory native skill copies; preserve complete directories before retiring them").action(async (options) => {
|
|
108791
108871
|
try {
|
|
108792
|
-
const discoveryInputs = options.discoveryInputs ? JSON.parse(
|
|
108872
|
+
const discoveryInputs = options.discoveryInputs ? JSON.parse(readFileSync38(options.discoveryInputs, "utf8")) : undefined;
|
|
108793
108873
|
if (options.targetManifest && (options.includeUnmanaged || options.includeVendor))
|
|
108794
108874
|
throw new Error("--target-manifest cannot be combined with broad native migration selectors");
|
|
108795
108875
|
const targetManifest = options.targetManifest ? readNativeMigrationTargetManifest(options.targetManifest) : undefined;
|
|
@@ -109094,11 +109174,11 @@ import {
|
|
|
109094
109174
|
copyFileSync as copyFileSync2,
|
|
109095
109175
|
mkdirSync as mkdirSync26,
|
|
109096
109176
|
readdirSync as readdirSync21,
|
|
109097
|
-
readFileSync as
|
|
109098
|
-
statSync as
|
|
109177
|
+
readFileSync as readFileSync39,
|
|
109178
|
+
statSync as statSync22,
|
|
109099
109179
|
writeFileSync as writeFileSync26
|
|
109100
109180
|
} from "fs";
|
|
109101
|
-
import { dirname as
|
|
109181
|
+
import { dirname as dirname31, join as join57, resolve as resolve23, sep as sep10 } from "path";
|
|
109102
109182
|
function fail5(code2, message, detail = []) {
|
|
109103
109183
|
throw new StationSnapshotError(code2, message, detail);
|
|
109104
109184
|
}
|
|
@@ -109110,7 +109190,7 @@ function readSnapshotManifest(repoRoot, stationId) {
|
|
|
109110
109190
|
const manifestPath = join57(snapshotRoot, "sync-manifest.json");
|
|
109111
109191
|
let manifest;
|
|
109112
109192
|
try {
|
|
109113
|
-
manifest = JSON.parse(
|
|
109193
|
+
manifest = JSON.parse(readFileSync39(manifestPath, "utf8"));
|
|
109114
109194
|
} catch (error61) {
|
|
109115
109195
|
fail5("MANIFEST_UNREADABLE", `cannot read snapshot manifest: ${manifestPath}: ${error61.message}`);
|
|
109116
109196
|
}
|
|
@@ -109192,7 +109272,7 @@ function planStationHydration(stationId, repoRoot) {
|
|
|
109192
109272
|
});
|
|
109193
109273
|
continue;
|
|
109194
109274
|
}
|
|
109195
|
-
const info =
|
|
109275
|
+
const info = statSync22(entry.fullPath);
|
|
109196
109276
|
const manifestHash = manifestHashes.get(`${agent}${MANIFEST_HASH_KEY_SEP}${homeRelative}`) ?? null;
|
|
109197
109277
|
let verified = false;
|
|
109198
109278
|
if (manifestHash !== null) {
|
|
@@ -109246,7 +109326,7 @@ function planStationHydration(stationId, repoRoot) {
|
|
|
109246
109326
|
for (const copy of copies) {
|
|
109247
109327
|
let isStub = false;
|
|
109248
109328
|
try {
|
|
109249
|
-
isStub = isPointerSkillMd(
|
|
109329
|
+
isStub = isPointerSkillMd(readFileSync39(copy.fullPath, "utf8"));
|
|
109250
109330
|
} catch {
|
|
109251
109331
|
isStub = false;
|
|
109252
109332
|
}
|
|
@@ -109351,7 +109431,7 @@ function writeStationHydration(options) {
|
|
|
109351
109431
|
}
|
|
109352
109432
|
let written = 0;
|
|
109353
109433
|
for (const entry of toWrite) {
|
|
109354
|
-
mkdirSync26(
|
|
109434
|
+
mkdirSync26(dirname31(entry.destination), { recursive: true });
|
|
109355
109435
|
copyFileSync2(entry.fullPath, entry.destination);
|
|
109356
109436
|
written += 1;
|
|
109357
109437
|
}
|
|
@@ -109372,8 +109452,8 @@ function writeStationHydration(options) {
|
|
|
109372
109452
|
},
|
|
109373
109453
|
skills: resultSkills
|
|
109374
109454
|
};
|
|
109375
|
-
const hydrationManifestPath = join57(
|
|
109376
|
-
mkdirSync26(
|
|
109455
|
+
const hydrationManifestPath = join57(dirname31(cacheRoot), `hydration-${options.stationId}.json`);
|
|
109456
|
+
mkdirSync26(dirname31(hydrationManifestPath), { recursive: true });
|
|
109377
109457
|
writeFileSync26(hydrationManifestPath, `${JSON.stringify(hydration, null, 2)}
|
|
109378
109458
|
`);
|
|
109379
109459
|
return {
|
|
@@ -109450,9 +109530,9 @@ var init_hydrate = __esm(() => {
|
|
|
109450
109530
|
|
|
109451
109531
|
// src/lib/prepare-skill.ts
|
|
109452
109532
|
import { createHash as createHash28, randomUUID as randomUUID11 } from "crypto";
|
|
109453
|
-
import { chmodSync as chmodSync3, existsSync as existsSync34, lstatSync as lstatSync29, mkdirSync as mkdirSync27, mkdtempSync as mkdtempSync6, readFileSync as
|
|
109533
|
+
import { chmodSync as chmodSync3, existsSync as existsSync34, lstatSync as lstatSync29, mkdirSync as mkdirSync27, mkdtempSync as mkdtempSync6, readFileSync as readFileSync40, readdirSync as readdirSync22, renameSync as renameSync12, rmSync as rmSync9, writeFileSync as writeFileSync27 } from "fs";
|
|
109454
109534
|
import { tmpdir as tmpdir2 } from "os";
|
|
109455
|
-
import { dirname as
|
|
109535
|
+
import { dirname as dirname32, isAbsolute as isAbsolute27, join as join58, relative as relative9, resolve as resolve24, sep as sep11 } from "path";
|
|
109456
109536
|
function prepareSkill(name, options) {
|
|
109457
109537
|
const normalized = normalizePortableSkillName(name);
|
|
109458
109538
|
if (!new RegExp(SEMVER_PATTERN).test(options.version))
|
|
@@ -109497,7 +109577,7 @@ function prepareSkill(name, options) {
|
|
|
109497
109577
|
mkdirSync27(join58(staging, directory2), { recursive: true });
|
|
109498
109578
|
for (const file2 of before2.files) {
|
|
109499
109579
|
const destination = join58(staging, file2.path);
|
|
109500
|
-
mkdirSync27(
|
|
109580
|
+
mkdirSync27(dirname32(destination), { recursive: true });
|
|
109501
109581
|
writeFileSync27(destination, file2.bytes, { mode: file2.mode });
|
|
109502
109582
|
}
|
|
109503
109583
|
const stagedManifest = join58(staging, "skill.json");
|
|
@@ -109558,7 +109638,7 @@ function validateRuntimeEntrypoint(candidate2, root2) {
|
|
|
109558
109638
|
if (typeof entry !== "string")
|
|
109559
109639
|
return;
|
|
109560
109640
|
const target = resolve24(root2, entry), rel = relative9(root2, target);
|
|
109561
|
-
if (
|
|
109641
|
+
if (isAbsolute27(entry) || /^[a-zA-Z]:/.test(entry) || entry.includes("\\") || !rel || rel === ".." || rel.startsWith(`..${sep11}`) || isAbsolute27(rel) || !existsSync34(target) || !lstatSync29(target).isFile()) {
|
|
109562
109642
|
throw new Error("Executable runtime.entrypoint must name an existing regular file inside the skill directory.");
|
|
109563
109643
|
}
|
|
109564
109644
|
}
|
|
@@ -109669,7 +109749,7 @@ function snapshot2(root2) {
|
|
|
109669
109749
|
bytes += stat3.size;
|
|
109670
109750
|
if (bytes > 50000000)
|
|
109671
109751
|
throw new Error("Skill exceeds the preparation size limit (50000000 bytes).");
|
|
109672
|
-
const content =
|
|
109752
|
+
const content = readFileSync40(absolute);
|
|
109673
109753
|
if (content.length !== stat3.size)
|
|
109674
109754
|
throw new Error("Skill changed during preparation.");
|
|
109675
109755
|
files.push({ path, bytes: content, mode: stat3.mode & 511 });
|
|
@@ -110071,7 +110151,7 @@ var init_schedule = __esm(() => {
|
|
|
110071
110151
|
|
|
110072
110152
|
// src/lib/registry-sync.ts
|
|
110073
110153
|
import { mkdirSync as mkdirSync28, writeFileSync as writeFileSync28 } from "fs";
|
|
110074
|
-
import { dirname as
|
|
110154
|
+
import { dirname as dirname33, relative as relative10 } from "path";
|
|
110075
110155
|
function createRegistrySyncArtifact(options = {}) {
|
|
110076
110156
|
const profile = options.profile ?? "all";
|
|
110077
110157
|
const includeDocs = options.includeDocs ?? true;
|
|
@@ -110128,7 +110208,7 @@ function createRegistrySyncArtifact(options = {}) {
|
|
|
110128
110208
|
};
|
|
110129
110209
|
}
|
|
110130
110210
|
function writeRegistrySyncArtifact(path, artifact) {
|
|
110131
|
-
mkdirSync28(
|
|
110211
|
+
mkdirSync28(dirname33(path), { recursive: true });
|
|
110132
110212
|
writeFileSync28(path, `${JSON.stringify(artifact, null, 2)}
|
|
110133
110213
|
`);
|
|
110134
110214
|
}
|
|
@@ -110349,8 +110429,8 @@ __export(exports_publish, {
|
|
|
110349
110429
|
buildVersionManifest: () => buildVersionManifest,
|
|
110350
110430
|
PushSkillError: () => PushSkillError
|
|
110351
110431
|
});
|
|
110352
|
-
import { execFileSync } from "child_process";
|
|
110353
|
-
import { existsSync as existsSync35, readFileSync as
|
|
110432
|
+
import { execFileSync as execFileSync2 } from "child_process";
|
|
110433
|
+
import { existsSync as existsSync35, readFileSync as readFileSync41 } from "fs";
|
|
110354
110434
|
import { hostname as hostname4 } from "os";
|
|
110355
110435
|
import { join as join59 } from "path";
|
|
110356
110436
|
function registerPublish(parent) {
|
|
@@ -110405,7 +110485,7 @@ async function pushSkill(name, options = {}) {
|
|
|
110405
110485
|
await verifyPackedCanonicalHash(skill.name, packed);
|
|
110406
110486
|
const versionManifest = buildVersionManifest(skill.path, packed);
|
|
110407
110487
|
const skillMdPath = join59(skill.path, "SKILL.md");
|
|
110408
|
-
const skillMd = existsSync35(skillMdPath) ?
|
|
110488
|
+
const skillMd = existsSync35(skillMdPath) ? readFileSync41(skillMdPath, "utf-8") : undefined;
|
|
110409
110489
|
const base3 = {
|
|
110410
110490
|
slug: skill.name,
|
|
110411
110491
|
path: skill.path,
|
|
@@ -110562,7 +110642,7 @@ function sanitizeGitRemote(url2) {
|
|
|
110562
110642
|
}
|
|
110563
110643
|
function gitValue(dir, args2) {
|
|
110564
110644
|
try {
|
|
110565
|
-
const out =
|
|
110645
|
+
const out = execFileSync2("git", ["-C", dir, ...args2], { stdio: ["ignore", "pipe", "ignore"], encoding: "utf-8" }).trim();
|
|
110566
110646
|
return out || null;
|
|
110567
110647
|
} catch {
|
|
110568
110648
|
return null;
|
|
@@ -112026,11 +112106,11 @@ var init_storage2 = __esm(() => {
|
|
|
112026
112106
|
});
|
|
112027
112107
|
|
|
112028
112108
|
// src/lib/registry-reconcile.ts
|
|
112029
|
-
import { existsSync as existsSync36, readFileSync as
|
|
112109
|
+
import { existsSync as existsSync36, readFileSync as readFileSync42, statSync as statSync23, writeFileSync as writeFileSync29 } from "fs";
|
|
112030
112110
|
import { join as join60 } from "path";
|
|
112031
112111
|
function isDirectory2(path) {
|
|
112032
112112
|
try {
|
|
112033
|
-
return
|
|
112113
|
+
return statSync23(path).isDirectory();
|
|
112034
112114
|
} catch {
|
|
112035
112115
|
return false;
|
|
112036
112116
|
}
|
|
@@ -112046,7 +112126,7 @@ function readBaseline(skillDir) {
|
|
|
112046
112126
|
if (!existsSync36(markerPath))
|
|
112047
112127
|
return;
|
|
112048
112128
|
try {
|
|
112049
|
-
const marker = JSON.parse(
|
|
112129
|
+
const marker = JSON.parse(readFileSync42(markerPath, "utf-8"));
|
|
112050
112130
|
if (!isSkillsOwnershipMarker(marker))
|
|
112051
112131
|
return;
|
|
112052
112132
|
return {
|
|
@@ -112062,7 +112142,7 @@ function readCursor(root2) {
|
|
|
112062
112142
|
if (!existsSync36(path))
|
|
112063
112143
|
return { runCount: 0 };
|
|
112064
112144
|
try {
|
|
112065
|
-
const cursor2 = JSON.parse(
|
|
112145
|
+
const cursor2 = JSON.parse(readFileSync42(path, "utf-8"));
|
|
112066
112146
|
return { runCount: typeof cursor2.runCount === "number" ? cursor2.runCount : 0 };
|
|
112067
112147
|
} catch {
|
|
112068
112148
|
return { runCount: 0 };
|
package/bin/mcp.js
CHANGED
|
@@ -20019,7 +20019,7 @@ var package_default;
|
|
|
20019
20019
|
var init_package = __esm(() => {
|
|
20020
20020
|
package_default = {
|
|
20021
20021
|
name: "@hasna/skills",
|
|
20022
|
-
version: "0.9.
|
|
20022
|
+
version: "0.9.9",
|
|
20023
20023
|
description: "Skills library for AI coding agents",
|
|
20024
20024
|
type: "module",
|
|
20025
20025
|
bin: {
|
package/bin/migrate.js
CHANGED
package/bin/server.js
CHANGED
|
@@ -24122,7 +24122,7 @@ var init_dist_es9 = __esm(() => {
|
|
|
24122
24122
|
// package.json
|
|
24123
24123
|
var package_default = {
|
|
24124
24124
|
name: "@hasna/skills",
|
|
24125
|
-
version: "0.9.
|
|
24125
|
+
version: "0.9.9",
|
|
24126
24126
|
description: "Skills library for AI coding agents",
|
|
24127
24127
|
type: "module",
|
|
24128
24128
|
bin: {
|
package/bin/worker.js
CHANGED
|
@@ -24125,7 +24125,7 @@ import { randomUUID as randomUUID6 } from "crypto";
|
|
|
24125
24125
|
// package.json
|
|
24126
24126
|
var package_default = {
|
|
24127
24127
|
name: "@hasna/skills",
|
|
24128
|
-
version: "0.9.
|
|
24128
|
+
version: "0.9.9",
|
|
24129
24129
|
description: "Skills library for AI coding agents",
|
|
24130
24130
|
type: "module",
|
|
24131
24131
|
bin: {
|
package/dist/index.js
CHANGED
|
@@ -11448,7 +11448,7 @@ import { isAbsolute as isAbsolute10, join as join20, resolve as resolve10 } from
|
|
|
11448
11448
|
// package.json
|
|
11449
11449
|
var package_default = {
|
|
11450
11450
|
name: "@hasna/skills",
|
|
11451
|
-
version: "0.9.
|
|
11451
|
+
version: "0.9.9",
|
|
11452
11452
|
description: "Skills library for AI coding agents",
|
|
11453
11453
|
type: "module",
|
|
11454
11454
|
bin: {
|
|
@@ -4,16 +4,26 @@ export interface CodexNativeHookTrustOptions {
|
|
|
4
4
|
home?: string;
|
|
5
5
|
dataDir?: string;
|
|
6
6
|
codexCommand?: string;
|
|
7
|
+
codexHome?: string;
|
|
7
8
|
apply?: boolean;
|
|
8
9
|
reviewedPlanDigest?: string;
|
|
9
10
|
reviewedSkillsCli?: ReviewedSkillsCli;
|
|
10
11
|
}
|
|
12
|
+
export interface SkillsCliReleaseProof {
|
|
13
|
+
packageTarPath: string;
|
|
14
|
+
packageTarSha256: string;
|
|
15
|
+
packageTarBytes: number;
|
|
16
|
+
manifestSha256: string;
|
|
17
|
+
executableSha256: string;
|
|
18
|
+
}
|
|
11
19
|
export interface CodexNativeHookReconcileOptions {
|
|
12
20
|
home?: string;
|
|
13
21
|
dataDir?: string;
|
|
14
22
|
codexCommand?: string;
|
|
15
23
|
journal: string;
|
|
16
24
|
reviewedSkillsCli?: ReviewedSkillsCli;
|
|
25
|
+
releaseProof?: SkillsCliReleaseProof;
|
|
26
|
+
supersedeBinding?: boolean;
|
|
17
27
|
}
|
|
18
28
|
type Connect = typeof connectCodexHookRpc;
|
|
19
29
|
/** Resolve an interrupted native write only after the native consumer and every
|
|
@@ -24,21 +34,27 @@ export declare function reconcileCodexNativeHooks(options: CodexNativeHookReconc
|
|
|
24
34
|
version: number;
|
|
25
35
|
status: string;
|
|
26
36
|
reconciled: boolean;
|
|
37
|
+
supersededBinding: boolean;
|
|
27
38
|
automaticRollback: boolean;
|
|
28
39
|
journal: string;
|
|
29
40
|
planDigest: any;
|
|
30
41
|
nativeVersion: string;
|
|
31
42
|
nativeStateVerified: boolean;
|
|
43
|
+
nativeTrustPending: boolean;
|
|
32
44
|
nativeExecutionVerified: boolean;
|
|
33
45
|
configSha256: string;
|
|
34
46
|
hooksSha256: string;
|
|
35
47
|
policySha256: string;
|
|
48
|
+
policyBeforeSha256: string;
|
|
49
|
+
policyCurrentSha256: string;
|
|
50
|
+
previousSkillsCli: any;
|
|
36
51
|
skillsCli: {
|
|
37
52
|
path: string;
|
|
38
53
|
version: string;
|
|
39
54
|
sha256: string;
|
|
40
55
|
manifestSha256: string;
|
|
41
56
|
};
|
|
57
|
+
releaseProof: SkillsCliReleaseProof | undefined;
|
|
42
58
|
nativeInventoryScope: string;
|
|
43
59
|
unrelatedNativeHooksPreserved: boolean;
|
|
44
60
|
unrelatedSettingsAndCommentsPreserved: boolean;
|
|
@@ -54,6 +70,7 @@ export declare function enrollCodexNativeHooks(options?: CodexNativeHookTrustOpt
|
|
|
54
70
|
manifestSha256: string;
|
|
55
71
|
};
|
|
56
72
|
nativeVersion: string;
|
|
73
|
+
nativeConfigPath: string;
|
|
57
74
|
ownedNativeProcessId: number | undefined;
|
|
58
75
|
agent: string;
|
|
59
76
|
applied: boolean;
|
package/dist/sdk/index.js
CHANGED
|
@@ -32373,7 +32373,7 @@ var init_event_sink = __esm(() => {
|
|
|
32373
32373
|
// package.json
|
|
32374
32374
|
var package_default = {
|
|
32375
32375
|
name: "@hasna/skills",
|
|
32376
|
-
version: "0.9.
|
|
32376
|
+
version: "0.9.9",
|
|
32377
32377
|
description: "Skills library for AI coding agents",
|
|
32378
32378
|
type: "module",
|
|
32379
32379
|
bin: {
|