@hasna/skills 0.10.57 → 0.10.59
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/index.js +72 -5
- package/bin/mcp.js +3 -2
- package/bin/migrate.js +1 -1
- package/bin/server.js +1 -1
- package/bin/worker.js +1 -1
- package/dist/index.js +4 -3
- package/dist/lib/claude-prospective-review.d.ts +1 -0
- package/dist/sdk/index.js +4 -3
- package/docs/plugin-admission.md +26 -1
- package/package.json +1 -1
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.59",
|
|
36892
36892
|
description: "Skills library for AI coding agents",
|
|
36893
36893
|
type: "module",
|
|
36894
36894
|
bin: {
|
|
@@ -40292,7 +40292,8 @@ var init_codex_native_compatibility = __esm(() => {
|
|
|
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
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
|
+
"codex-cli 0.161.0": ["hooks", "qualified-skill-catalog", "installed-plugin-review"],
|
|
40296
|
+
"codex-cli 0.162.0": ["hooks", "qualified-skill-catalog", "installed-plugin-review"]
|
|
40296
40297
|
};
|
|
40297
40298
|
SUPPORTED_CODEX_HOOK_VERSIONS = Object.freeze(Object.keys(MEASURED_CODEX_CAPABILITIES).filter((version) => supportsCodexNativeCapability(version, "hooks")));
|
|
40298
40299
|
});
|
|
@@ -51944,7 +51945,7 @@ async function connectCodexHookRpc(options) {
|
|
|
51944
51945
|
const deadline = setTimeout(() => {
|
|
51945
51946
|
clearTimeout(terminate);
|
|
51946
51947
|
reject2(new Error("CODEX_HOOK_TRUST_NATIVE_CLOSE_UNCONFIRMED"));
|
|
51947
|
-
},
|
|
51948
|
+
}, 1e4);
|
|
51948
51949
|
actualClose.then(() => {
|
|
51949
51950
|
clearTimeout(terminate);
|
|
51950
51951
|
clearTimeout(deadline);
|
|
@@ -116855,7 +116856,7 @@ function reviewClaudeProspectiveCandidate(request2, requestFileSha256) {
|
|
|
116855
116856
|
const pluginRootStat = lstatSync37(pluginRoot, { throwIfNoEntry: false });
|
|
116856
116857
|
if (pluginRootStat && (!pluginRootStat.isDirectory() || pluginRootStat.isSymbolicLink()))
|
|
116857
116858
|
refuse6("Claude plugin root is not a regular directory");
|
|
116858
|
-
keys3(request2.candidate, ["marketplace", "root", "catalogPath", "catalogSha256", "closureSha256", "plugins", ...hasOwn2(request2.candidate, "releaseManifest") ? ["releaseManifest"] : [], ...hasOwn2(request2.candidate, "functionHooksEnv") ? ["functionHooksEnv"] : []], "candidate");
|
|
116859
|
+
keys3(request2.candidate, ["marketplace", "root", "catalogPath", "catalogSha256", "closureSha256", "plugins", ...hasOwn2(request2.candidate, "releaseManifest") ? ["releaseManifest"] : [], ...hasOwn2(request2.candidate, "functionHooksEnv") ? ["functionHooksEnv"] : [], ...hasOwn2(request2.candidate, "settingsMarketplaceSource") ? ["settingsMarketplaceSource"] : []], "candidate");
|
|
116859
116860
|
const candidate2 = request2.candidate;
|
|
116860
116861
|
canonicalDir(candidate2.root, "candidate root");
|
|
116861
116862
|
if (typeof candidate2.marketplace !== "string" || !/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/.test(candidate2.marketplace))
|
|
@@ -116864,6 +116865,8 @@ function reviewClaudeProspectiveCandidate(request2, requestFileSha256) {
|
|
|
116864
116865
|
refuse6("candidate must select between one and 32 plugins from one marketplace");
|
|
116865
116866
|
if (candidate2.functionHooksEnv !== undefined && candidate2.functionHooksEnv !== "1")
|
|
116866
116867
|
refuse6("function-hook environment mutation only supports the explicit value 1");
|
|
116868
|
+
if (hasOwn2(candidate2, "settingsMarketplaceSource") && (candidate2.settingsMarketplaceSource !== "directory" || request2.scope.kind !== "user" || !["2.1.293", "2.1.293 (Claude Code)"].includes(request2.native.executable.version)))
|
|
116869
|
+
refuse6("settings marketplace source operation requires directory source and the measured Claude 2.1.293 user scope");
|
|
116867
116870
|
abs(candidate2.catalogPath, "catalog path");
|
|
116868
116871
|
if (!candidate2.catalogPath.startsWith(candidate2.root + sep15))
|
|
116869
116872
|
refuse6("catalog must be inside the frozen candidate root");
|
|
@@ -117010,6 +117013,30 @@ function reviewClaudeProspectiveCandidate(request2, requestFileSha256) {
|
|
|
117010
117013
|
const registrations = jsonFile(expectedPaths.installedPlugins, "Claude installed plugins");
|
|
117011
117014
|
if (registrations && (registrations.version !== 2 || !object11(registrations.plugins)))
|
|
117012
117015
|
refuse6("current installed plugin registry has an unsupported shape");
|
|
117016
|
+
if (candidate2.settingsMarketplaceSource === "directory" && registrations) {
|
|
117017
|
+
keys3(registrations, ["version", "plugins"], "current complete installed plugin registry");
|
|
117018
|
+
for (const rows of Object.values(registrations.plugins)) {
|
|
117019
|
+
if (!Array.isArray(rows))
|
|
117020
|
+
refuse6("current installed plugin rows are not an array");
|
|
117021
|
+
for (const row2 of rows) {
|
|
117022
|
+
if (!object11(row2))
|
|
117023
|
+
refuse6("current installed plugin row is not an object");
|
|
117024
|
+
keys3(row2, ["scope", "installPath", "version", "installedAt", "lastUpdated", ...Object.hasOwn(row2, "projectPath") ? ["projectPath"] : [], ...Object.hasOwn(row2, "gitCommitSha") ? ["gitCommitSha"] : []], "current complete installed plugin row");
|
|
117025
|
+
if (!["user", "project", "local"].includes(row2.scope) || typeof row2.version !== "string" || !row2.version)
|
|
117026
|
+
refuse6("current installed plugin scope or version is invalid");
|
|
117027
|
+
abs(row2.installPath, "current installed plugin path");
|
|
117028
|
+
if (row2.scope === "user") {
|
|
117029
|
+
if (Object.hasOwn(row2, "projectPath"))
|
|
117030
|
+
refuse6("current user plugin row has a project path");
|
|
117031
|
+
} else
|
|
117032
|
+
abs(row2.projectPath, "current installed plugin project path");
|
|
117033
|
+
if (!validUtcTimestamp(row2.installedAt) || !validUtcTimestamp(row2.lastUpdated))
|
|
117034
|
+
refuse6("current installed plugin timestamps are invalid");
|
|
117035
|
+
if (Object.hasOwn(row2, "gitCommitSha") && (typeof row2.gitCommitSha !== "string" || !/^[a-f0-9]{40}$/.test(row2.gitCommitSha)))
|
|
117036
|
+
refuse6("current installed plugin Git commit is outside the measured preservation contract");
|
|
117037
|
+
}
|
|
117038
|
+
}
|
|
117039
|
+
}
|
|
117013
117040
|
const settingsAfter = settings ? structuredClone(settings) : {};
|
|
117014
117041
|
if (settingsAfter.enabledPlugins === undefined)
|
|
117015
117042
|
settingsAfter.enabledPlugins = {};
|
|
@@ -117087,8 +117114,48 @@ function reviewClaudeProspectiveCandidate(request2, requestFileSha256) {
|
|
|
117087
117114
|
refuse6("target settings env is not an object");
|
|
117088
117115
|
settingsAfter.env = { ...env3, CLAUDE_CODE_ENABLE_FUNCTION_HOOKS: "1" };
|
|
117089
117116
|
}
|
|
117117
|
+
if (candidate2.settingsMarketplaceSource === "directory") {
|
|
117118
|
+
const extra = settingsAfter.extraKnownMarketplaces === undefined ? {} : settingsAfter.extraKnownMarketplaces;
|
|
117119
|
+
if (!object11(extra))
|
|
117120
|
+
refuse6("current extraKnownMarketplaces is not an object");
|
|
117121
|
+
for (const [name, row2] of Object.entries(extra)) {
|
|
117122
|
+
if (!object11(row2))
|
|
117123
|
+
refuse6("current settings marketplace row is not an object");
|
|
117124
|
+
const allowed = name === candidate2.marketplace ? ["source"] : ["source", "autoUpdate"];
|
|
117125
|
+
if (Object.keys(row2).some((key) => !allowed.includes(key)) || !Object.hasOwn(row2, "source"))
|
|
117126
|
+
refuse6("current settings marketplace metadata cannot be preserved by the measured native operation");
|
|
117127
|
+
if (Object.hasOwn(row2, "autoUpdate") && typeof row2.autoUpdate !== "boolean")
|
|
117128
|
+
refuse6("current settings marketplace autoUpdate is not a boolean");
|
|
117129
|
+
keys3(row2.source, ["source", "path"], "current settings marketplace directory source");
|
|
117130
|
+
if (row2.source.source !== "directory")
|
|
117131
|
+
refuse6("current settings marketplace source is outside the measured directory contract");
|
|
117132
|
+
abs(row2.source.path, "current settings marketplace directory path");
|
|
117133
|
+
}
|
|
117134
|
+
settingsAfter.extraKnownMarketplaces = { ...extra, [candidate2.marketplace]: { source: { source: "directory", path: candidate2.root } } };
|
|
117135
|
+
for (const row2 of Object.values(marketplaces ?? {})) {
|
|
117136
|
+
if (!object11(row2))
|
|
117137
|
+
refuse6("current known marketplace row is not an object");
|
|
117138
|
+
keys3(row2, ["source", "installLocation", "lastUpdated", ...Object.hasOwn(row2, "autoUpdate") ? ["autoUpdate"] : []], "current known marketplace row");
|
|
117139
|
+
if (!object11(row2.source))
|
|
117140
|
+
refuse6("current known marketplace source is not an object");
|
|
117141
|
+
if (row2.source.source === "directory") {
|
|
117142
|
+
keys3(row2.source, ["source", "path"], "current known marketplace directory source");
|
|
117143
|
+
abs(row2.source.path, "current known marketplace directory path");
|
|
117144
|
+
} else if (row2.source.source === "github") {
|
|
117145
|
+
keys3(row2.source, ["source", "repo"], "current known marketplace GitHub source");
|
|
117146
|
+
if (typeof row2.source.repo !== "string" || row2.source.repo.length > 512 || !/^[A-Za-z0-9][A-Za-z0-9_.-]*\/[A-Za-z0-9][A-Za-z0-9_.-]*$/.test(row2.source.repo))
|
|
117147
|
+
refuse6("current known marketplace GitHub repository is not an owner/repository identifier");
|
|
117148
|
+
} else
|
|
117149
|
+
refuse6("current known marketplace source is outside the measured preservation contract");
|
|
117150
|
+
abs(row2.installLocation, "current known marketplace install location");
|
|
117151
|
+
if (!validUtcTimestamp(row2.lastUpdated))
|
|
117152
|
+
refuse6("current known marketplace timestamp is invalid");
|
|
117153
|
+
if (Object.hasOwn(row2, "autoUpdate") && typeof row2.autoUpdate !== "boolean")
|
|
117154
|
+
refuse6("current known marketplace autoUpdate is not a boolean");
|
|
117155
|
+
}
|
|
117156
|
+
}
|
|
117090
117157
|
if (!isDeepStrictEqual18(delta.settingsAfter, settingsAfter))
|
|
117091
|
-
refuse6("complete settings document differs from the exact selected plugin/options/environment operations");
|
|
117158
|
+
refuse6("complete settings document differs from the exact selected plugin/options/environment/marketplace operations");
|
|
117092
117159
|
const marketplaceRowBefore = marketplaces?.[candidate2.marketplace];
|
|
117093
117160
|
if (marketplaceRowBefore !== undefined && !object11(marketplaceRowBefore))
|
|
117094
117161
|
refuse6("current marketplace row has an unsupported shape");
|
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.59",
|
|
20023
20023
|
description: "Skills library for AI coding agents",
|
|
20024
20024
|
type: "module",
|
|
20025
20025
|
bin: {
|
|
@@ -38561,7 +38561,8 @@ var init_codex_native_compatibility = __esm(() => {
|
|
|
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
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
|
+
"codex-cli 0.161.0": ["hooks", "qualified-skill-catalog", "installed-plugin-review"],
|
|
38565
|
+
"codex-cli 0.162.0": ["hooks", "qualified-skill-catalog", "installed-plugin-review"]
|
|
38565
38566
|
};
|
|
38566
38567
|
SUPPORTED_CODEX_HOOK_VERSIONS = Object.freeze(Object.keys(MEASURED_CODEX_CAPABILITIES).filter((version2) => supportsCodexNativeCapability(version2, "hooks")));
|
|
38567
38568
|
});
|
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.59",
|
|
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.59",
|
|
24147
24147
|
description: "Skills library for AI coding agents",
|
|
24148
24148
|
type: "module",
|
|
24149
24149
|
bin: {
|
package/dist/index.js
CHANGED
|
@@ -9399,7 +9399,8 @@ var MEASURED_CODEX_CAPABILITIES = {
|
|
|
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
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
|
+
"codex-cli 0.161.0": ["hooks", "qualified-skill-catalog", "installed-plugin-review"],
|
|
9403
|
+
"codex-cli 0.162.0": ["hooks", "qualified-skill-catalog", "installed-plugin-review"]
|
|
9403
9404
|
};
|
|
9404
9405
|
function supportsCodexNativeCapability(version, capability) {
|
|
9405
9406
|
return typeof version === "string" && Object.hasOwn(MEASURED_CODEX_CAPABILITIES, version) && MEASURED_CODEX_CAPABILITIES[version].includes(capability);
|
|
@@ -11833,7 +11834,7 @@ function replaceSkillSession(expected, replacement, plan, options = {}, beforeCo
|
|
|
11833
11834
|
// package.json
|
|
11834
11835
|
var package_default = {
|
|
11835
11836
|
name: "@hasna/skills",
|
|
11836
|
-
version: "0.10.
|
|
11837
|
+
version: "0.10.59",
|
|
11837
11838
|
description: "Skills library for AI coding agents",
|
|
11838
11839
|
type: "module",
|
|
11839
11840
|
bin: {
|
|
@@ -14062,7 +14063,7 @@ async function connectCodexHookRpc(options) {
|
|
|
14062
14063
|
const deadline = setTimeout(() => {
|
|
14063
14064
|
clearTimeout(terminate);
|
|
14064
14065
|
reject(new Error("CODEX_HOOK_TRUST_NATIVE_CLOSE_UNCONFIRMED"));
|
|
14065
|
-
},
|
|
14066
|
+
}, 1e4);
|
|
14066
14067
|
actualClose.then(() => {
|
|
14067
14068
|
clearTimeout(terminate);
|
|
14068
14069
|
clearTimeout(deadline);
|
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.59",
|
|
32377
32377
|
description: "Skills library for AI coding agents",
|
|
32378
32378
|
type: "module",
|
|
32379
32379
|
bin: {
|
|
@@ -38469,7 +38469,8 @@ var MEASURED_CODEX_CAPABILITIES = {
|
|
|
38469
38469
|
"codex-cli 0.159.2": ["hooks", "qualified-skill-catalog"],
|
|
38470
38470
|
"codex-cli 0.160.0": ["hooks", "qualified-skill-catalog", "installed-plugin-review"],
|
|
38471
38471
|
"codex-cli 0.160.1": ["hooks", "qualified-skill-catalog", "installed-plugin-review"],
|
|
38472
|
-
"codex-cli 0.161.0": ["hooks", "qualified-skill-catalog", "installed-plugin-review"]
|
|
38472
|
+
"codex-cli 0.161.0": ["hooks", "qualified-skill-catalog", "installed-plugin-review"],
|
|
38473
|
+
"codex-cli 0.162.0": ["hooks", "qualified-skill-catalog", "installed-plugin-review"]
|
|
38473
38474
|
};
|
|
38474
38475
|
function supportsCodexNativeCapability(version, capability) {
|
|
38475
38476
|
return typeof version === "string" && Object.hasOwn(MEASURED_CODEX_CAPABILITIES, version) && MEASURED_CODEX_CAPABILITIES[version].includes(capability);
|
|
@@ -38611,7 +38612,7 @@ async function connectCodexHookRpc(options) {
|
|
|
38611
38612
|
const deadline = setTimeout(() => {
|
|
38612
38613
|
clearTimeout(terminate);
|
|
38613
38614
|
reject(new Error("CODEX_HOOK_TRUST_NATIVE_CLOSE_UNCONFIRMED"));
|
|
38614
|
-
},
|
|
38615
|
+
}, 1e4);
|
|
38615
38616
|
actualClose.then(() => {
|
|
38616
38617
|
clearTimeout(terminate);
|
|
38617
38618
|
clearTimeout(deadline);
|
package/docs/plugin-admission.md
CHANGED
|
@@ -194,7 +194,32 @@ closure. Nontrivial `metadata.pluginRoot` values and native catalog or selected
|
|
|
194
194
|
plugin dependency declarations refuse because this validator does not resolve
|
|
195
195
|
or review unselected external plugins.
|
|
196
196
|
The request may declare `functionHooksEnv: "1"`; without that declaration the
|
|
197
|
-
environment document is preserved unchanged.
|
|
197
|
+
environment document is preserved unchanged. For a measured Claude 2.1.293
|
|
198
|
+
user-scoped install, `candidate.settingsMarketplaceSource: "directory"`
|
|
199
|
+
explicitly declares the native settings registration. Skills derives
|
|
200
|
+
`extraKnownMarketplaces[candidate.marketplace].source` from the exact frozen
|
|
201
|
+
candidate root. The measured operation accepts existing directory sources
|
|
202
|
+
only. Foreign entries may also carry a boolean `autoUpdate`; other metadata
|
|
203
|
+
refuses before writing because the native parser drops unknown fields.
|
|
204
|
+
Selected-entry metadata, including `autoUpdate`, also refuses because this
|
|
205
|
+
Claude release replaces that entire entry. The complete supplied settings
|
|
206
|
+
document must match the derived projection, preserving all foreign entries.
|
|
207
|
+
The same declared operation preflights every authoritative
|
|
208
|
+
`known_marketplaces.json` row: exact `source`, `installLocation`, `lastUpdated`
|
|
209
|
+
and optional boolean `autoUpdate`. Sources are either `{source: "directory",
|
|
210
|
+
path: <normalized absolute path>}` or `{source: "github", repo: "owner/repository"}`.
|
|
211
|
+
Other source keys and row metadata refuse before the native parser can drop them.
|
|
212
|
+
The complete `installed_plugins.json` document must contain only `version` and
|
|
213
|
+
`plugins`. Every existing row, including untouched plugins and other scopes,
|
|
214
|
+
must have `scope`, `installPath`, `version`, `installedAt` and `lastUpdated`,
|
|
215
|
+
with a project path for project/local scope and an optional 40-character
|
|
216
|
+
lowercase hexadecimal `gitCommitSha`. Unsupported metadata or malformed fields
|
|
217
|
+
refuse before installation; supported foreign rows remain exact in the required
|
|
218
|
+
after-document. Existing selected-row restrictions still apply.
|
|
219
|
+
Omission preserves the settings field unchanged; other values, versions and project scope
|
|
220
|
+
refuse. The installer must still verify the actual native executable and
|
|
221
|
+
poststate; a supplied version string does not establish consumer identity.
|
|
222
|
+
The validator shallow-merges
|
|
198
223
|
each declared options patch into the selected plugin's existing `options`;
|
|
199
224
|
the patch must explicitly bind `enabled: true`, and the validator enforces that
|
|
200
225
|
value after merging. This preserves all other selected options and unrelated
|