@hasna/skills 0.10.52 → 0.10.54
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 +3 -3
- package/bin/index.js +40 -10
- package/bin/mcp.js +39 -9
- package/bin/migrate.js +1 -1
- package/bin/server.js +1 -1
- package/bin/worker.js +1 -1
- package/dist/index.js +40 -10
- package/dist/sdk/index.js +40 -10
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -643,9 +643,9 @@ skills hook native-catalog --cwd /absolute/project --output /private/catalog.jso
|
|
|
643
643
|
skills hook install --agent codex --codex-native-catalog /private/catalog.json --json
|
|
644
644
|
```
|
|
645
645
|
|
|
646
|
-
Codex 0.159.2, 0.160.0
|
|
646
|
+
Codex 0.159.2, 0.160.0, 0.160.1 and 0.161.0 have measured qualified-name catalog support.
|
|
647
647
|
Native transport, capture and review use one capability registry of exact
|
|
648
|
-
releases. Unmeasured releases, including 0.160.2 and 0.161.
|
|
648
|
+
releases. Unmeasured releases, including 0.160.2 and 0.161.1, refuse until the
|
|
649
649
|
native catalog/name-denial and hook-dispatch acceptance tests pass; an RPC
|
|
650
650
|
handshake alone does not establish those semantics. Admitting a release does not
|
|
651
651
|
admit its corpus: the transport still requires the existing native corpus
|
|
@@ -697,7 +697,7 @@ different extant, witnessed user version. Individual missing files, current
|
|
|
697
697
|
registered roots, aliases and registration changes still refuse; historical
|
|
698
698
|
source hashes and typed settings witnesses remain intact.
|
|
699
699
|
|
|
700
|
-
For a Codex 0.160.0
|
|
700
|
+
For a Codex 0.160.0, 0.160.1 or 0.161.0 remote refresh omitted by an existing qualified-name disable,
|
|
701
701
|
a fresh native catalog and discovery review can plan the new exact path disable
|
|
702
702
|
in the same transaction. The remote installation receipt, namespace and capability
|
|
703
703
|
controls must match; conflicting enable rules, unknown names and ambiguous
|
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.
|
|
36891
|
+
version: "0.10.54",
|
|
36892
36892
|
description: "Skills library for AI coding agents",
|
|
36893
36893
|
type: "module",
|
|
36894
36894
|
bin: {
|
|
@@ -40291,7 +40291,8 @@ var init_codex_native_compatibility = __esm(() => {
|
|
|
40291
40291
|
"codex-cli 0.159.0": ["hooks"],
|
|
40292
40292
|
"codex-cli 0.159.2": ["hooks", "qualified-skill-catalog"],
|
|
40293
40293
|
"codex-cli 0.160.0": ["hooks", "qualified-skill-catalog", "installed-plugin-review"],
|
|
40294
|
-
"codex-cli 0.160.1": ["hooks", "qualified-skill-catalog", "installed-plugin-review"]
|
|
40294
|
+
"codex-cli 0.160.1": ["hooks", "qualified-skill-catalog", "installed-plugin-review"],
|
|
40295
|
+
"codex-cli 0.161.0": ["hooks", "qualified-skill-catalog", "installed-plugin-review"]
|
|
40295
40296
|
};
|
|
40296
40297
|
SUPPORTED_CODEX_HOOK_VERSIONS = Object.freeze(Object.keys(MEASURED_CODEX_CAPABILITIES).filter((version) => supportsCodexNativeCapability(version, "hooks")));
|
|
40297
40298
|
});
|
|
@@ -59505,12 +59506,17 @@ function captureRetiredCodexDiscovery(binding, controls, rules) {
|
|
|
59505
59506
|
return { ...current, codexRetiredMaterializations: previous };
|
|
59506
59507
|
return { ...current, codexRetiredMaterializations: { roots, parents: parents3, directories: captureDiscoveryDirectoryProjection(directories.map((item) => item.path), roots) } };
|
|
59507
59508
|
}
|
|
59509
|
+
function retainableAbsentSource(source) {
|
|
59510
|
+
if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined)
|
|
59511
|
+
return false;
|
|
59512
|
+
return [undefined, "bytes"].includes(source.hashMode) || source.hashMode === "claude-plugin-manifest-v1" && source.sha256 !== null && source.path.endsWith(join37(sep8, ".claude-plugin", "plugin.json"));
|
|
59513
|
+
}
|
|
59508
59514
|
function absentRetiredClaudeRoots(binding) {
|
|
59509
59515
|
if (binding.agent !== "claude" || binding.method !== "reviewed")
|
|
59510
59516
|
return [];
|
|
59511
59517
|
const result2 = new Set;
|
|
59512
59518
|
for (const source of binding.sources) {
|
|
59513
|
-
if (
|
|
59519
|
+
if (!retainableAbsentSource(source) || source.sha256 === null)
|
|
59514
59520
|
continue;
|
|
59515
59521
|
const marker = sep8 + ".claude" + sep8 + "plugins" + sep8 + "cache" + sep8, at2 = source.path.indexOf(marker);
|
|
59516
59522
|
if (at2 < 0 || source.path.indexOf(marker, at2 + 1) >= 0)
|
|
@@ -59535,17 +59541,41 @@ function absentRetiredClaudeRoots(binding) {
|
|
|
59535
59541
|
continue;
|
|
59536
59542
|
if (JSON.stringify(config.hooks ?? {}).includes(root2))
|
|
59537
59543
|
continue;
|
|
59544
|
+
const registrationScope = (row) => {
|
|
59545
|
+
if (!row || typeof row !== "object" || Array.isArray(row))
|
|
59546
|
+
return null;
|
|
59547
|
+
const value = row;
|
|
59548
|
+
if (typeof value.installPath !== "string" || /[\x00-\x1f\x7f]/.test(value.installPath) || !isAbsolute22(value.installPath) || resolve21(value.installPath) !== value.installPath || value.installPath.length > AGENT_POLICY_LIMITS.pathCharacters)
|
|
59549
|
+
return null;
|
|
59550
|
+
if (value.scope === "user")
|
|
59551
|
+
return value.projectPath === undefined || value.projectPath === null ? "user\x00" : null;
|
|
59552
|
+
if (value.scope === "project")
|
|
59553
|
+
return typeof value.projectPath === "string" && !/[\x00-\x1f\x7f]/.test(value.projectPath) && value.projectPath.length <= AGENT_POLICY_LIMITS.pathCharacters && isAbsolute22(value.projectPath) && resolve21(value.projectPath) === value.projectPath ? `project\x00${value.projectPath}` : null;
|
|
59554
|
+
return null;
|
|
59555
|
+
};
|
|
59556
|
+
if (Object.values(installed.plugins).some((value) => !Array.isArray(value) || value.some((row) => !row || typeof row.installPath !== "string" || row.installPath === root2 || row.installPath.startsWith(root2 + sep8) || root2.startsWith(row.installPath + sep8))))
|
|
59557
|
+
continue;
|
|
59538
59558
|
const rows = installed.plugins[id];
|
|
59539
|
-
if (!Array.isArray(rows) || rows.length
|
|
59559
|
+
if (!Array.isArray(rows) || rows.length < 1)
|
|
59540
59560
|
continue;
|
|
59541
|
-
const
|
|
59542
|
-
|
|
59561
|
+
const targetScopes = new Set;
|
|
59562
|
+
let targetValid = true;
|
|
59563
|
+
for (const row of rows) {
|
|
59564
|
+
const scope = registrationScope(row), value = row;
|
|
59565
|
+
if (scope === null || targetScopes.has(scope) || value?.installPath !== rows[0]?.installPath || value?.version !== rows[0]?.version) {
|
|
59566
|
+
targetValid = false;
|
|
59567
|
+
break;
|
|
59568
|
+
}
|
|
59569
|
+
targetScopes.add(scope);
|
|
59570
|
+
}
|
|
59571
|
+
if (!targetValid || !targetScopes.has("user\x00"))
|
|
59572
|
+
continue;
|
|
59573
|
+
const active = rows[0]?.installPath;
|
|
59574
|
+
if (typeof active !== "string" || rows[0]?.version !== basename11(active) || dirname20(active) !== dirname20(root2) || active === root2 || !lstatSync25(active, { throwIfNoEntry: false })?.isDirectory() || realpathSync11(active) !== active)
|
|
59543
59575
|
continue;
|
|
59544
59576
|
const activeManifest = full(join37(active, ".claude-plugin/plugin.json"));
|
|
59545
59577
|
if (!activeManifest || projected(activeManifest) !== activeManifest.sha256)
|
|
59546
59578
|
continue;
|
|
59547
|
-
if (Object.values(installed.plugins).some((value) => !Array.isArray(value) || value.some((row) => !row || typeof row.installPath !== "string" || row.installPath === root2 || row.installPath.startsWith(root2 + sep8) || root2.startsWith(row.installPath + sep8))))
|
|
59548
|
-
continue;
|
|
59549
59579
|
result2.add(root2);
|
|
59550
59580
|
}
|
|
59551
59581
|
return [...result2];
|
|
@@ -59598,7 +59628,7 @@ function verifyAgentDiscovery(binding, codexRecovery) {
|
|
|
59598
59628
|
safe4(source.path);
|
|
59599
59629
|
continue;
|
|
59600
59630
|
}
|
|
59601
|
-
if (absentRoots.some((root2) => source.path.startsWith(root2 + sep8)) &&
|
|
59631
|
+
if (absentRoots.some((root2) => source.path.startsWith(root2 + sep8)) && retainableAbsentSource(source)) {
|
|
59602
59632
|
safe4(source.path);
|
|
59603
59633
|
continue;
|
|
59604
59634
|
}
|
|
@@ -59654,7 +59684,7 @@ function rebindAgentDiscovery(binding, changes) {
|
|
|
59654
59684
|
const installationRoots = codexInstallationRoots(binding), absentRoots = [...absentCodexSkillRoots(binding), ...absentRetiredClaudeRoots(binding), ...retiredCodexRoots(binding).filter((root2) => !lstatSync25(root2, { throwIfNoEntry: false }))];
|
|
59655
59685
|
const rebound = { ...binding, sources: binding.sources.map((source) => {
|
|
59656
59686
|
assertMarketplaceBinding(binding, source);
|
|
59657
|
-
if (!changes.has(source.path) && (installationRoots.some((root2) => source.path.startsWith(root2 + sep8)) || absentRoots.some((root2) => source.path.startsWith(root2 + sep8)) &&
|
|
59687
|
+
if (!changes.has(source.path) && (installationRoots.some((root2) => source.path.startsWith(root2 + sep8)) || absentRoots.some((root2) => source.path.startsWith(root2 + sep8)) && retainableAbsentSource(source)))
|
|
59658
59688
|
return source;
|
|
59659
59689
|
const sha2563 = projected(source, changes, budget2);
|
|
59660
59690
|
if (!changes.has(source.path) && sha2563 !== source.sha256)
|
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.10.
|
|
20022
|
+
version: "0.10.54",
|
|
20023
20023
|
description: "Skills library for AI coding agents",
|
|
20024
20024
|
type: "module",
|
|
20025
20025
|
bin: {
|
|
@@ -38560,7 +38560,8 @@ var init_codex_native_compatibility = __esm(() => {
|
|
|
38560
38560
|
"codex-cli 0.159.0": ["hooks"],
|
|
38561
38561
|
"codex-cli 0.159.2": ["hooks", "qualified-skill-catalog"],
|
|
38562
38562
|
"codex-cli 0.160.0": ["hooks", "qualified-skill-catalog", "installed-plugin-review"],
|
|
38563
|
-
"codex-cli 0.160.1": ["hooks", "qualified-skill-catalog", "installed-plugin-review"]
|
|
38563
|
+
"codex-cli 0.160.1": ["hooks", "qualified-skill-catalog", "installed-plugin-review"],
|
|
38564
|
+
"codex-cli 0.161.0": ["hooks", "qualified-skill-catalog", "installed-plugin-review"]
|
|
38564
38565
|
};
|
|
38565
38566
|
SUPPORTED_CODEX_HOOK_VERSIONS = Object.freeze(Object.keys(MEASURED_CODEX_CAPABILITIES).filter((version2) => supportsCodexNativeCapability(version2, "hooks")));
|
|
38566
38567
|
});
|
|
@@ -50916,12 +50917,17 @@ function retiredCodexRoots(binding) {
|
|
|
50916
50917
|
}
|
|
50917
50918
|
return proof.roots;
|
|
50918
50919
|
}
|
|
50920
|
+
function retainableAbsentSource(source) {
|
|
50921
|
+
if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined)
|
|
50922
|
+
return false;
|
|
50923
|
+
return [undefined, "bytes"].includes(source.hashMode) || source.hashMode === "claude-plugin-manifest-v1" && source.sha256 !== null && source.path.endsWith(join26(sep6, ".claude-plugin", "plugin.json"));
|
|
50924
|
+
}
|
|
50919
50925
|
function absentRetiredClaudeRoots(binding) {
|
|
50920
50926
|
if (binding.agent !== "claude" || binding.method !== "reviewed")
|
|
50921
50927
|
return [];
|
|
50922
50928
|
const result = new Set;
|
|
50923
50929
|
for (const source of binding.sources) {
|
|
50924
|
-
if (
|
|
50930
|
+
if (!retainableAbsentSource(source) || source.sha256 === null)
|
|
50925
50931
|
continue;
|
|
50926
50932
|
const marker = sep6 + ".claude" + sep6 + "plugins" + sep6 + "cache" + sep6, at = source.path.indexOf(marker);
|
|
50927
50933
|
if (at < 0 || source.path.indexOf(marker, at + 1) >= 0)
|
|
@@ -50946,17 +50952,41 @@ function absentRetiredClaudeRoots(binding) {
|
|
|
50946
50952
|
continue;
|
|
50947
50953
|
if (JSON.stringify(config2.hooks ?? {}).includes(root))
|
|
50948
50954
|
continue;
|
|
50955
|
+
const registrationScope = (row) => {
|
|
50956
|
+
if (!row || typeof row !== "object" || Array.isArray(row))
|
|
50957
|
+
return null;
|
|
50958
|
+
const value = row;
|
|
50959
|
+
if (typeof value.installPath !== "string" || /[\x00-\x1f\x7f]/.test(value.installPath) || !isAbsolute15(value.installPath) || resolve17(value.installPath) !== value.installPath || value.installPath.length > AGENT_POLICY_LIMITS.pathCharacters)
|
|
50960
|
+
return null;
|
|
50961
|
+
if (value.scope === "user")
|
|
50962
|
+
return value.projectPath === undefined || value.projectPath === null ? "user\x00" : null;
|
|
50963
|
+
if (value.scope === "project")
|
|
50964
|
+
return typeof value.projectPath === "string" && !/[\x00-\x1f\x7f]/.test(value.projectPath) && value.projectPath.length <= AGENT_POLICY_LIMITS.pathCharacters && isAbsolute15(value.projectPath) && resolve17(value.projectPath) === value.projectPath ? `project\x00${value.projectPath}` : null;
|
|
50965
|
+
return null;
|
|
50966
|
+
};
|
|
50967
|
+
if (Object.values(installed.plugins).some((value) => !Array.isArray(value) || value.some((row) => !row || typeof row.installPath !== "string" || row.installPath === root || row.installPath.startsWith(root + sep6) || root.startsWith(row.installPath + sep6))))
|
|
50968
|
+
continue;
|
|
50949
50969
|
const rows = installed.plugins[id];
|
|
50950
|
-
if (!Array.isArray(rows) || rows.length
|
|
50970
|
+
if (!Array.isArray(rows) || rows.length < 1)
|
|
50951
50971
|
continue;
|
|
50952
|
-
const
|
|
50953
|
-
|
|
50972
|
+
const targetScopes = new Set;
|
|
50973
|
+
let targetValid = true;
|
|
50974
|
+
for (const row of rows) {
|
|
50975
|
+
const scope = registrationScope(row), value = row;
|
|
50976
|
+
if (scope === null || targetScopes.has(scope) || value?.installPath !== rows[0]?.installPath || value?.version !== rows[0]?.version) {
|
|
50977
|
+
targetValid = false;
|
|
50978
|
+
break;
|
|
50979
|
+
}
|
|
50980
|
+
targetScopes.add(scope);
|
|
50981
|
+
}
|
|
50982
|
+
if (!targetValid || !targetScopes.has("user\x00"))
|
|
50983
|
+
continue;
|
|
50984
|
+
const active = rows[0]?.installPath;
|
|
50985
|
+
if (typeof active !== "string" || rows[0]?.version !== basename9(active) || dirname16(active) !== dirname16(root) || active === root || !lstatSync18(active, { throwIfNoEntry: false })?.isDirectory() || realpathSync5(active) !== active)
|
|
50954
50986
|
continue;
|
|
50955
50987
|
const activeManifest = full(join26(active, ".claude-plugin/plugin.json"));
|
|
50956
50988
|
if (!activeManifest || projected(activeManifest) !== activeManifest.sha256)
|
|
50957
50989
|
continue;
|
|
50958
|
-
if (Object.values(installed.plugins).some((value) => !Array.isArray(value) || value.some((row) => !row || typeof row.installPath !== "string" || row.installPath === root || row.installPath.startsWith(root + sep6) || root.startsWith(row.installPath + sep6))))
|
|
50959
|
-
continue;
|
|
50960
50990
|
result.add(root);
|
|
50961
50991
|
}
|
|
50962
50992
|
return [...result];
|
|
@@ -51009,7 +51039,7 @@ function verifyAgentDiscovery(binding, codexRecovery) {
|
|
|
51009
51039
|
safe4(source.path);
|
|
51010
51040
|
continue;
|
|
51011
51041
|
}
|
|
51012
|
-
if (absentRoots.some((root) => source.path.startsWith(root + sep6)) &&
|
|
51042
|
+
if (absentRoots.some((root) => source.path.startsWith(root + sep6)) && retainableAbsentSource(source)) {
|
|
51013
51043
|
safe4(source.path);
|
|
51014
51044
|
continue;
|
|
51015
51045
|
}
|
package/bin/migrate.js
CHANGED
package/bin/server.js
CHANGED
|
@@ -24140,7 +24140,7 @@ restoreLaunchCwd();
|
|
|
24140
24140
|
// package.json
|
|
24141
24141
|
var package_default = {
|
|
24142
24142
|
name: "@hasna/skills",
|
|
24143
|
-
version: "0.10.
|
|
24143
|
+
version: "0.10.54",
|
|
24144
24144
|
description: "Skills library for AI coding agents",
|
|
24145
24145
|
type: "module",
|
|
24146
24146
|
bin: {
|
package/bin/worker.js
CHANGED
|
@@ -24143,7 +24143,7 @@ import { randomUUID as randomUUID6 } from "crypto";
|
|
|
24143
24143
|
// package.json
|
|
24144
24144
|
var package_default = {
|
|
24145
24145
|
name: "@hasna/skills",
|
|
24146
|
-
version: "0.10.
|
|
24146
|
+
version: "0.10.54",
|
|
24147
24147
|
description: "Skills library for AI coding agents",
|
|
24148
24148
|
type: "module",
|
|
24149
24149
|
bin: {
|
package/dist/index.js
CHANGED
|
@@ -9398,7 +9398,8 @@ var MEASURED_CODEX_CAPABILITIES = {
|
|
|
9398
9398
|
"codex-cli 0.159.0": ["hooks"],
|
|
9399
9399
|
"codex-cli 0.159.2": ["hooks", "qualified-skill-catalog"],
|
|
9400
9400
|
"codex-cli 0.160.0": ["hooks", "qualified-skill-catalog", "installed-plugin-review"],
|
|
9401
|
-
"codex-cli 0.160.1": ["hooks", "qualified-skill-catalog", "installed-plugin-review"]
|
|
9401
|
+
"codex-cli 0.160.1": ["hooks", "qualified-skill-catalog", "installed-plugin-review"],
|
|
9402
|
+
"codex-cli 0.161.0": ["hooks", "qualified-skill-catalog", "installed-plugin-review"]
|
|
9402
9403
|
};
|
|
9403
9404
|
function supportsCodexNativeCapability(version, capability) {
|
|
9404
9405
|
return typeof version === "string" && Object.hasOwn(MEASURED_CODEX_CAPABILITIES, version) && MEASURED_CODEX_CAPABILITIES[version].includes(capability);
|
|
@@ -11832,7 +11833,7 @@ function replaceSkillSession(expected, replacement, plan, options = {}, beforeCo
|
|
|
11832
11833
|
// package.json
|
|
11833
11834
|
var package_default = {
|
|
11834
11835
|
name: "@hasna/skills",
|
|
11835
|
-
version: "0.10.
|
|
11836
|
+
version: "0.10.54",
|
|
11836
11837
|
description: "Skills library for AI coding agents",
|
|
11837
11838
|
type: "module",
|
|
11838
11839
|
bin: {
|
|
@@ -20837,12 +20838,17 @@ function captureRetiredCodexDiscovery(binding, controls, rules) {
|
|
|
20837
20838
|
return { ...current, codexRetiredMaterializations: previous };
|
|
20838
20839
|
return { ...current, codexRetiredMaterializations: { roots, parents: parents3, directories: captureDiscoveryDirectoryProjection(directories.map((item) => item.path), roots) } };
|
|
20839
20840
|
}
|
|
20841
|
+
function retainableAbsentSource(source) {
|
|
20842
|
+
if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined)
|
|
20843
|
+
return false;
|
|
20844
|
+
return [undefined, "bytes"].includes(source.hashMode) || source.hashMode === "claude-plugin-manifest-v1" && source.sha256 !== null && source.path.endsWith(join32(sep8, ".claude-plugin", "plugin.json"));
|
|
20845
|
+
}
|
|
20840
20846
|
function absentRetiredClaudeRoots(binding) {
|
|
20841
20847
|
if (binding.agent !== "claude" || binding.method !== "reviewed")
|
|
20842
20848
|
return [];
|
|
20843
20849
|
const result = new Set;
|
|
20844
20850
|
for (const source of binding.sources) {
|
|
20845
|
-
if (
|
|
20851
|
+
if (!retainableAbsentSource(source) || source.sha256 === null)
|
|
20846
20852
|
continue;
|
|
20847
20853
|
const marker = sep8 + ".claude" + sep8 + "plugins" + sep8 + "cache" + sep8, at = source.path.indexOf(marker);
|
|
20848
20854
|
if (at < 0 || source.path.indexOf(marker, at + 1) >= 0)
|
|
@@ -20867,17 +20873,41 @@ function absentRetiredClaudeRoots(binding) {
|
|
|
20867
20873
|
continue;
|
|
20868
20874
|
if (JSON.stringify(config.hooks ?? {}).includes(root2))
|
|
20869
20875
|
continue;
|
|
20876
|
+
const registrationScope = (row) => {
|
|
20877
|
+
if (!row || typeof row !== "object" || Array.isArray(row))
|
|
20878
|
+
return null;
|
|
20879
|
+
const value = row;
|
|
20880
|
+
if (typeof value.installPath !== "string" || /[\x00-\x1f\x7f]/.test(value.installPath) || !isAbsolute21(value.installPath) || resolve20(value.installPath) !== value.installPath || value.installPath.length > AGENT_POLICY_LIMITS.pathCharacters)
|
|
20881
|
+
return null;
|
|
20882
|
+
if (value.scope === "user")
|
|
20883
|
+
return value.projectPath === undefined || value.projectPath === null ? "user\x00" : null;
|
|
20884
|
+
if (value.scope === "project")
|
|
20885
|
+
return typeof value.projectPath === "string" && !/[\x00-\x1f\x7f]/.test(value.projectPath) && value.projectPath.length <= AGENT_POLICY_LIMITS.pathCharacters && isAbsolute21(value.projectPath) && resolve20(value.projectPath) === value.projectPath ? `project\x00${value.projectPath}` : null;
|
|
20886
|
+
return null;
|
|
20887
|
+
};
|
|
20888
|
+
if (Object.values(installed.plugins).some((value) => !Array.isArray(value) || value.some((row) => !row || typeof row.installPath !== "string" || row.installPath === root2 || row.installPath.startsWith(root2 + sep8) || root2.startsWith(row.installPath + sep8))))
|
|
20889
|
+
continue;
|
|
20870
20890
|
const rows = installed.plugins[id];
|
|
20871
|
-
if (!Array.isArray(rows) || rows.length
|
|
20891
|
+
if (!Array.isArray(rows) || rows.length < 1)
|
|
20872
20892
|
continue;
|
|
20873
|
-
const
|
|
20874
|
-
|
|
20893
|
+
const targetScopes = new Set;
|
|
20894
|
+
let targetValid = true;
|
|
20895
|
+
for (const row of rows) {
|
|
20896
|
+
const scope = registrationScope(row), value = row;
|
|
20897
|
+
if (scope === null || targetScopes.has(scope) || value?.installPath !== rows[0]?.installPath || value?.version !== rows[0]?.version) {
|
|
20898
|
+
targetValid = false;
|
|
20899
|
+
break;
|
|
20900
|
+
}
|
|
20901
|
+
targetScopes.add(scope);
|
|
20902
|
+
}
|
|
20903
|
+
if (!targetValid || !targetScopes.has("user\x00"))
|
|
20904
|
+
continue;
|
|
20905
|
+
const active = rows[0]?.installPath;
|
|
20906
|
+
if (typeof active !== "string" || rows[0]?.version !== basename11(active) || dirname20(active) !== dirname20(root2) || active === root2 || !lstatSync25(active, { throwIfNoEntry: false })?.isDirectory() || realpathSync11(active) !== active)
|
|
20875
20907
|
continue;
|
|
20876
20908
|
const activeManifest = full(join32(active, ".claude-plugin/plugin.json"));
|
|
20877
20909
|
if (!activeManifest || projected(activeManifest) !== activeManifest.sha256)
|
|
20878
20910
|
continue;
|
|
20879
|
-
if (Object.values(installed.plugins).some((value) => !Array.isArray(value) || value.some((row) => !row || typeof row.installPath !== "string" || row.installPath === root2 || row.installPath.startsWith(root2 + sep8) || root2.startsWith(row.installPath + sep8))))
|
|
20880
|
-
continue;
|
|
20881
20911
|
result.add(root2);
|
|
20882
20912
|
}
|
|
20883
20913
|
return [...result];
|
|
@@ -20930,7 +20960,7 @@ function verifyAgentDiscovery(binding, codexRecovery) {
|
|
|
20930
20960
|
safe4(source.path);
|
|
20931
20961
|
continue;
|
|
20932
20962
|
}
|
|
20933
|
-
if (absentRoots.some((root2) => source.path.startsWith(root2 + sep8)) &&
|
|
20963
|
+
if (absentRoots.some((root2) => source.path.startsWith(root2 + sep8)) && retainableAbsentSource(source)) {
|
|
20934
20964
|
safe4(source.path);
|
|
20935
20965
|
continue;
|
|
20936
20966
|
}
|
|
@@ -20986,7 +21016,7 @@ function rebindAgentDiscovery(binding, changes) {
|
|
|
20986
21016
|
const installationRoots = codexInstallationRoots(binding), absentRoots = [...absentCodexSkillRoots(binding), ...absentRetiredClaudeRoots(binding), ...retiredCodexRoots(binding).filter((root2) => !lstatSync25(root2, { throwIfNoEntry: false }))];
|
|
20987
21017
|
const rebound = { ...binding, sources: binding.sources.map((source) => {
|
|
20988
21018
|
assertMarketplaceBinding(binding, source);
|
|
20989
|
-
if (!changes.has(source.path) && (installationRoots.some((root2) => source.path.startsWith(root2 + sep8)) || absentRoots.some((root2) => source.path.startsWith(root2 + sep8)) &&
|
|
21019
|
+
if (!changes.has(source.path) && (installationRoots.some((root2) => source.path.startsWith(root2 + sep8)) || absentRoots.some((root2) => source.path.startsWith(root2 + sep8)) && retainableAbsentSource(source)))
|
|
20990
21020
|
return source;
|
|
20991
21021
|
const sha2563 = projected(source, changes, budget2);
|
|
20992
21022
|
if (!changes.has(source.path) && sha2563 !== source.sha256)
|
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.10.
|
|
32376
|
+
version: "0.10.54",
|
|
32377
32377
|
description: "Skills library for AI coding agents",
|
|
32378
32378
|
type: "module",
|
|
32379
32379
|
bin: {
|
|
@@ -38446,7 +38446,8 @@ var MEASURED_CODEX_CAPABILITIES = {
|
|
|
38446
38446
|
"codex-cli 0.159.0": ["hooks"],
|
|
38447
38447
|
"codex-cli 0.159.2": ["hooks", "qualified-skill-catalog"],
|
|
38448
38448
|
"codex-cli 0.160.0": ["hooks", "qualified-skill-catalog", "installed-plugin-review"],
|
|
38449
|
-
"codex-cli 0.160.1": ["hooks", "qualified-skill-catalog", "installed-plugin-review"]
|
|
38449
|
+
"codex-cli 0.160.1": ["hooks", "qualified-skill-catalog", "installed-plugin-review"],
|
|
38450
|
+
"codex-cli 0.161.0": ["hooks", "qualified-skill-catalog", "installed-plugin-review"]
|
|
38450
38451
|
};
|
|
38451
38452
|
function supportsCodexNativeCapability(version, capability) {
|
|
38452
38453
|
return typeof version === "string" && Object.hasOwn(MEASURED_CODEX_CAPABILITIES, version) && MEASURED_CODEX_CAPABILITIES[version].includes(capability);
|
|
@@ -43655,12 +43656,17 @@ function captureRetiredCodexDiscovery(binding, controls, rules) {
|
|
|
43655
43656
|
return { ...current, codexRetiredMaterializations: previous };
|
|
43656
43657
|
return { ...current, codexRetiredMaterializations: { roots, parents: parents3, directories: captureDiscoveryDirectoryProjection(directories.map((item) => item.path), roots) } };
|
|
43657
43658
|
}
|
|
43659
|
+
function retainableAbsentSource(source) {
|
|
43660
|
+
if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined)
|
|
43661
|
+
return false;
|
|
43662
|
+
return [undefined, "bytes"].includes(source.hashMode) || source.hashMode === "claude-plugin-manifest-v1" && source.sha256 !== null && source.path.endsWith(join26(sep6, ".claude-plugin", "plugin.json"));
|
|
43663
|
+
}
|
|
43658
43664
|
function absentRetiredClaudeRoots(binding) {
|
|
43659
43665
|
if (binding.agent !== "claude" || binding.method !== "reviewed")
|
|
43660
43666
|
return [];
|
|
43661
43667
|
const result = new Set;
|
|
43662
43668
|
for (const source of binding.sources) {
|
|
43663
|
-
if (
|
|
43669
|
+
if (!retainableAbsentSource(source) || source.sha256 === null)
|
|
43664
43670
|
continue;
|
|
43665
43671
|
const marker = sep6 + ".claude" + sep6 + "plugins" + sep6 + "cache" + sep6, at = source.path.indexOf(marker);
|
|
43666
43672
|
if (at < 0 || source.path.indexOf(marker, at + 1) >= 0)
|
|
@@ -43685,17 +43691,41 @@ function absentRetiredClaudeRoots(binding) {
|
|
|
43685
43691
|
continue;
|
|
43686
43692
|
if (JSON.stringify(config.hooks ?? {}).includes(root2))
|
|
43687
43693
|
continue;
|
|
43694
|
+
const registrationScope = (row) => {
|
|
43695
|
+
if (!row || typeof row !== "object" || Array.isArray(row))
|
|
43696
|
+
return null;
|
|
43697
|
+
const value = row;
|
|
43698
|
+
if (typeof value.installPath !== "string" || /[\x00-\x1f\x7f]/.test(value.installPath) || !isAbsolute20(value.installPath) || resolve19(value.installPath) !== value.installPath || value.installPath.length > AGENT_POLICY_LIMITS.pathCharacters)
|
|
43699
|
+
return null;
|
|
43700
|
+
if (value.scope === "user")
|
|
43701
|
+
return value.projectPath === undefined || value.projectPath === null ? "user\x00" : null;
|
|
43702
|
+
if (value.scope === "project")
|
|
43703
|
+
return typeof value.projectPath === "string" && !/[\x00-\x1f\x7f]/.test(value.projectPath) && value.projectPath.length <= AGENT_POLICY_LIMITS.pathCharacters && isAbsolute20(value.projectPath) && resolve19(value.projectPath) === value.projectPath ? `project\x00${value.projectPath}` : null;
|
|
43704
|
+
return null;
|
|
43705
|
+
};
|
|
43706
|
+
if (Object.values(installed.plugins).some((value) => !Array.isArray(value) || value.some((row) => !row || typeof row.installPath !== "string" || row.installPath === root2 || row.installPath.startsWith(root2 + sep6) || root2.startsWith(row.installPath + sep6))))
|
|
43707
|
+
continue;
|
|
43688
43708
|
const rows = installed.plugins[id2];
|
|
43689
|
-
if (!Array.isArray(rows) || rows.length
|
|
43709
|
+
if (!Array.isArray(rows) || rows.length < 1)
|
|
43690
43710
|
continue;
|
|
43691
|
-
const
|
|
43692
|
-
|
|
43711
|
+
const targetScopes = new Set;
|
|
43712
|
+
let targetValid = true;
|
|
43713
|
+
for (const row of rows) {
|
|
43714
|
+
const scope = registrationScope(row), value = row;
|
|
43715
|
+
if (scope === null || targetScopes.has(scope) || value?.installPath !== rows[0]?.installPath || value?.version !== rows[0]?.version) {
|
|
43716
|
+
targetValid = false;
|
|
43717
|
+
break;
|
|
43718
|
+
}
|
|
43719
|
+
targetScopes.add(scope);
|
|
43720
|
+
}
|
|
43721
|
+
if (!targetValid || !targetScopes.has("user\x00"))
|
|
43722
|
+
continue;
|
|
43723
|
+
const active = rows[0]?.installPath;
|
|
43724
|
+
if (typeof active !== "string" || rows[0]?.version !== basename9(active) || dirname17(active) !== dirname17(root2) || active === root2 || !lstatSync21(active, { throwIfNoEntry: false })?.isDirectory() || realpathSync9(active) !== active)
|
|
43693
43725
|
continue;
|
|
43694
43726
|
const activeManifest = full(join26(active, ".claude-plugin/plugin.json"));
|
|
43695
43727
|
if (!activeManifest || projected(activeManifest) !== activeManifest.sha256)
|
|
43696
43728
|
continue;
|
|
43697
|
-
if (Object.values(installed.plugins).some((value) => !Array.isArray(value) || value.some((row) => !row || typeof row.installPath !== "string" || row.installPath === root2 || row.installPath.startsWith(root2 + sep6) || root2.startsWith(row.installPath + sep6))))
|
|
43698
|
-
continue;
|
|
43699
43729
|
result.add(root2);
|
|
43700
43730
|
}
|
|
43701
43731
|
return [...result];
|
|
@@ -43748,7 +43778,7 @@ function verifyAgentDiscovery(binding, codexRecovery) {
|
|
|
43748
43778
|
safe4(source.path);
|
|
43749
43779
|
continue;
|
|
43750
43780
|
}
|
|
43751
|
-
if (absentRoots.some((root2) => source.path.startsWith(root2 + sep6)) &&
|
|
43781
|
+
if (absentRoots.some((root2) => source.path.startsWith(root2 + sep6)) && retainableAbsentSource(source)) {
|
|
43752
43782
|
safe4(source.path);
|
|
43753
43783
|
continue;
|
|
43754
43784
|
}
|
|
@@ -43804,7 +43834,7 @@ function rebindAgentDiscovery(binding, changes) {
|
|
|
43804
43834
|
const installationRoots = codexInstallationRoots(binding), absentRoots = [...absentCodexSkillRoots(binding), ...absentRetiredClaudeRoots(binding), ...retiredCodexRoots(binding).filter((root2) => !lstatSync21(root2, { throwIfNoEntry: false }))];
|
|
43805
43835
|
const rebound = { ...binding, sources: binding.sources.map((source) => {
|
|
43806
43836
|
assertMarketplaceBinding(binding, source);
|
|
43807
|
-
if (!changes.has(source.path) && (installationRoots.some((root2) => source.path.startsWith(root2 + sep6)) || absentRoots.some((root2) => source.path.startsWith(root2 + sep6)) &&
|
|
43837
|
+
if (!changes.has(source.path) && (installationRoots.some((root2) => source.path.startsWith(root2 + sep6)) || absentRoots.some((root2) => source.path.startsWith(root2 + sep6)) && retainableAbsentSource(source)))
|
|
43808
43838
|
return source;
|
|
43809
43839
|
const sha2562 = projected(source, changes, budget2);
|
|
43810
43840
|
if (!changes.has(source.path) && sha2562 !== source.sha256)
|