@hasna/skills 0.9.8 → 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 +24 -13
- 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 +2 -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;
|
|
@@ -108301,10 +108306,10 @@ async function reconcileCodexNativeHooks(options, connect = connectCodexHookRpc)
|
|
|
108301
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 }));
|
|
108302
108307
|
const admitted = intent.admitted ?? intent.hooks;
|
|
108303
108308
|
const configSha256 = intent.configSha256 ?? configBefore.sha256, configVersion = intent.configVersion ?? intent.expectedVersion;
|
|
108304
|
-
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 };
|
|
108305
108310
|
need4(makePlanDigest(digestInput) === intent.planDigest, "RECONCILE_PLAN_CHANGED");
|
|
108306
108311
|
need4(isDeepStrictEqual6(intent.hooks, admitted.filter((hook) => !hook.enabled || hook.trustStatus !== "trusted")), "RECONCILE_INTENT_HOOKS_CHANGED");
|
|
108307
|
-
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");
|
|
108308
108313
|
const policyCurrent = snapshot(join56(dataDir3, "agent-policy.json"), true);
|
|
108309
108314
|
let supersededBinding = false;
|
|
108310
108315
|
if (policyCurrent.sha256 !== policyBefore.sha256) {
|
|
@@ -108342,8 +108347,11 @@ async function reconcileCodexNativeHooks(options, connect = connectCodexHookRpc)
|
|
|
108342
108347
|
verifyReleaseArtifact(options.releaseProof, skillsCli);
|
|
108343
108348
|
const skillsBindingChanged = !isDeepStrictEqual6(skillsCli.receipt, intent.skillsCli);
|
|
108344
108349
|
need4(!skillsBindingChanged || supersededBinding, "RECONCILE_SKILLS_BINDING_CHANGED");
|
|
108345
|
-
const alias = binding.rootAliases?.find((item) => item.agent === "codex"),
|
|
108346
|
-
need4(resolve22(intent.configPath) === resolve22(join56(
|
|
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);
|
|
108347
108355
|
const hooksCurrent = snapshot(hooksPath);
|
|
108348
108356
|
if (hooksCurrent.sha256 !== intent.hooksSha256 && hooksCurrent.sha256 !== hooksBefore.sha256) {
|
|
108349
108357
|
need4(supersededBinding, "RECONCILE_HOOKS_CHANGED");
|
|
@@ -108391,12 +108399,12 @@ async function reconcileCodexNativeHooks(options, connect = connectCodexHookRpc)
|
|
|
108391
108399
|
}
|
|
108392
108400
|
}
|
|
108393
108401
|
const config2 = await rpc.request("config/read", { includeLayers: true, cwd: home });
|
|
108394
|
-
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);
|
|
108395
108403
|
need4(layers?.length === 1 && !layers[0].disabledReason && isDeepStrictEqual6(layers[0].config, current), "RECONCILE_NATIVE_CONFIG_MISMATCH");
|
|
108396
108404
|
const finalDiscovery = await rpc.request("hooks/list", { cwds: [home] });
|
|
108397
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");
|
|
108398
108406
|
const finalConfig = await rpc.request("config/read", { includeLayers: true, cwd: home });
|
|
108399
|
-
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);
|
|
108400
108408
|
need4(finalLayers?.length === 1 && isDeepStrictEqual6(finalLayers[0].config, current), "RECONCILE_NATIVE_CONFIG_CHANGED");
|
|
108401
108409
|
unchanged2(stoppedFile);
|
|
108402
108410
|
unchanged2(intentFile);
|
|
@@ -108426,7 +108434,10 @@ async function enrollCodexNativeHooks(options = {}, connect = connectCodexHookRp
|
|
|
108426
108434
|
const policyFile = snapshot(join56(dataDir3, "agent-policy.json"), true), policy = parseManagedSkillPolicy(policyFile.text);
|
|
108427
108435
|
const binding = policy.bridge, alias = binding.rootAliases?.find((item) => item.agent === "codex");
|
|
108428
108436
|
const skillsCli = bindSkillsCli(binding.commands.codex, options.reviewedSkillsCli);
|
|
108429
|
-
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");
|
|
108430
108441
|
const hooksFile = snapshot(hooksPath), configFile = snapshot(configPath, true), original = structure(configFile.text);
|
|
108431
108442
|
const declarations = JSON.parse(hooksFile.text).hooks, expected = [];
|
|
108432
108443
|
for (const [event, [nativeEvent, label]] of Object.entries(eventNames)) {
|
|
@@ -108457,7 +108468,7 @@ async function enrollCodexNativeHooks(options = {}, connect = connectCodexHookRp
|
|
|
108457
108468
|
});
|
|
108458
108469
|
const discovered = await list2(), admitted = admit(discovered);
|
|
108459
108470
|
const config2 = await rpc.request("config/read", { includeLayers: true, cwd: home });
|
|
108460
|
-
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);
|
|
108461
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");
|
|
108462
108473
|
need4(config2.config && config2.config.features?.hooks !== false, "NATIVE_HOOKS_DISABLED");
|
|
108463
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");
|
|
@@ -108471,9 +108482,9 @@ async function enrollCodexNativeHooks(options = {}, connect = connectCodexHookRp
|
|
|
108471
108482
|
unchanged2(configFile);
|
|
108472
108483
|
};
|
|
108473
108484
|
checkInputs();
|
|
108474
|
-
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 };
|
|
108475
108486
|
const planDigest = makePlanDigest(digestInput);
|
|
108476
|
-
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 };
|
|
108477
108488
|
if (options.apply)
|
|
108478
108489
|
need4(options.reviewedPlanDigest === planDigest, "PLAN_CHANGED: run the dry-run again and pass its reviewed --plan-digest with --apply");
|
|
108479
108490
|
const parent = join56(dataDir3, "native-hook-trust");
|
|
@@ -108727,7 +108738,7 @@ function registerAgentIntegration(parent) {
|
|
|
108727
108738
|
throw new Error("Native trust enrollment requires --agent codex");
|
|
108728
108739
|
if (options.agent !== "codex")
|
|
108729
108740
|
throw new Error("Native trust enrollment currently supports --agent codex only");
|
|
108730
|
-
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 });
|
|
108731
108742
|
if (options.json)
|
|
108732
108743
|
await writeCliOutput(JSON.stringify(result2));
|
|
108733
108744
|
else
|
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,6 +4,7 @@ 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;
|
|
@@ -69,6 +70,7 @@ export declare function enrollCodexNativeHooks(options?: CodexNativeHookTrustOpt
|
|
|
69
70
|
manifestSha256: string;
|
|
70
71
|
};
|
|
71
72
|
nativeVersion: string;
|
|
73
|
+
nativeConfigPath: string;
|
|
72
74
|
ownedNativeProcessId: number | undefined;
|
|
73
75
|
agent: string;
|
|
74
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: {
|