skillset 0.1.0-beta.9 → 0.13.0
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/dist/cli.js +175 -17
- package/dist/create.js +175 -17
- package/package.json +2 -3
package/dist/cli.js
CHANGED
|
@@ -7517,12 +7517,12 @@ var skillsetFeatureRegistry = defineFeatureRegistry([
|
|
|
7517
7517
|
status: "externally_managed"
|
|
7518
7518
|
},
|
|
7519
7519
|
cursor: {
|
|
7520
|
-
evidence: [docs("docs/features/runtime-adapters.md"), fixture("fixtures/external/repos
|
|
7520
|
+
evidence: [docs("docs/features/runtime-adapters.md"), fixture("fixtures/external/repos.yaml")],
|
|
7521
7521
|
reason: "Cursor support needs target documentation and adapter evidence before Skillset can lower or distribute it.",
|
|
7522
7522
|
status: "planned"
|
|
7523
7523
|
},
|
|
7524
7524
|
"gemini-cli": {
|
|
7525
|
-
evidence: [docs("docs/features/runtime-adapters.md"), fixture("fixtures/external/repos
|
|
7525
|
+
evidence: [docs("docs/features/runtime-adapters.md"), fixture("fixtures/external/repos.yaml")],
|
|
7526
7526
|
reason: "Gemini support needs target documentation and adapter evidence before Skillset can lower or distribute it.",
|
|
7527
7527
|
status: "planned"
|
|
7528
7528
|
},
|
|
@@ -7537,7 +7537,7 @@ var skillsetFeatureRegistry = defineFeatureRegistry([
|
|
|
7537
7537
|
status: "future"
|
|
7538
7538
|
},
|
|
7539
7539
|
opencode: {
|
|
7540
|
-
evidence: [docs("docs/features/runtime-adapters.md"), fixture("fixtures/external/repos
|
|
7540
|
+
evidence: [docs("docs/features/runtime-adapters.md"), fixture("fixtures/external/repos.yaml")],
|
|
7541
7541
|
reason: "OpenCode support needs target documentation and adapter evidence before Skillset can lower or distribute it.",
|
|
7542
7542
|
status: "planned"
|
|
7543
7543
|
}
|
|
@@ -7624,7 +7624,7 @@ var skillsetFeatureRegistry = defineFeatureRegistry([
|
|
|
7624
7624
|
status: "implemented",
|
|
7625
7625
|
summary: "Normalizes tool policy intent into Claude allowed-tools fields and Codex metadata sidecars.",
|
|
7626
7626
|
targetSupport: {
|
|
7627
|
-
claude: { status: "
|
|
7627
|
+
claude: { status: "transformed" },
|
|
7628
7628
|
codex: { status: "metadata_only" }
|
|
7629
7629
|
},
|
|
7630
7630
|
title: "Tool Intent",
|
|
@@ -7679,6 +7679,9 @@ function defineFeatureRegistry(entries) {
|
|
|
7679
7679
|
assertRuntimeSupportVocabulary(entries);
|
|
7680
7680
|
return [...entries].sort((left, right) => compareStrings(left.id, right.id));
|
|
7681
7681
|
}
|
|
7682
|
+
function listSkillsetFeatures(registry = skillsetFeatureRegistry) {
|
|
7683
|
+
return registry;
|
|
7684
|
+
}
|
|
7682
7685
|
function getSkillsetFeature(id, registry = skillsetFeatureRegistry) {
|
|
7683
7686
|
return registry.find((entry) => entry.id === id);
|
|
7684
7687
|
}
|
|
@@ -14447,6 +14450,9 @@ async function exists6(path) {
|
|
|
14447
14450
|
throw error;
|
|
14448
14451
|
}
|
|
14449
14452
|
}
|
|
14453
|
+
// packages/core/src/host-leak.ts
|
|
14454
|
+
var textDecoder3 = new TextDecoder;
|
|
14455
|
+
|
|
14450
14456
|
// packages/core/src/normalized-output-tree.ts
|
|
14451
14457
|
var DEFAULT_STRUCTURED_JSON_BASENAMES = new Set([".skillset.lock"]);
|
|
14452
14458
|
|
|
@@ -14454,7 +14460,7 @@ var DEFAULT_STRUCTURED_JSON_BASENAMES = new Set([".skillset.lock"]);
|
|
|
14454
14460
|
var textEncoder4 = new TextEncoder;
|
|
14455
14461
|
// packages/core/src/destination-ownership.ts
|
|
14456
14462
|
import { basename as basename3 } from "path";
|
|
14457
|
-
var
|
|
14463
|
+
var textDecoder4 = new TextDecoder;
|
|
14458
14464
|
function classifyDestinationOwnership(args) {
|
|
14459
14465
|
const file = classifyFileOwnership(args.path, args.target);
|
|
14460
14466
|
const fields = args.content === undefined ? [] : classifyFieldOwnership(args.path, args.target, args.content);
|
|
@@ -14493,7 +14499,7 @@ function classifyFieldOwnership(path, target, content) {
|
|
|
14493
14499
|
return [];
|
|
14494
14500
|
let record;
|
|
14495
14501
|
try {
|
|
14496
|
-
const parsed = JSON.parse(
|
|
14502
|
+
const parsed = JSON.parse(textDecoder4.decode(content));
|
|
14497
14503
|
if (!isJsonRecord(parsed))
|
|
14498
14504
|
return [];
|
|
14499
14505
|
record = parsed;
|
|
@@ -19064,7 +19070,7 @@ async function exists12(path2) {
|
|
|
19064
19070
|
|
|
19065
19071
|
// apps/skillset/src/authoring.ts
|
|
19066
19072
|
import { resolve as resolve8, relative as relative15 } from "path";
|
|
19067
|
-
var
|
|
19073
|
+
var textDecoder5 = new TextDecoder;
|
|
19068
19074
|
async function explainPath(rootPath, inputPath, options = {}) {
|
|
19069
19075
|
const graph = await loadBuildGraph(rootPath, options);
|
|
19070
19076
|
const allRendered = await renderBuildGraph(graph);
|
|
@@ -19077,33 +19083,39 @@ async function explainPath(rootPath, inputPath, options = {}) {
|
|
|
19077
19083
|
const items = collectLockItems(rendered);
|
|
19078
19084
|
const asSource = items.filter((item) => item.sourcePath === target);
|
|
19079
19085
|
if (asSource.length > 0) {
|
|
19086
|
+
const matchedLoweringOutcomes = explainLoweringOutcomes(target, asSource, loweringOutcomes);
|
|
19080
19087
|
return {
|
|
19081
19088
|
path: target,
|
|
19082
19089
|
kind: explainSourceKind(graph, target),
|
|
19083
19090
|
entries: asSource.map((item) => item.entry),
|
|
19084
|
-
|
|
19091
|
+
features: featureCapabilitiesForPath(graph, target, asSource, matchedLoweringOutcomes),
|
|
19092
|
+
loweringOutcomes: matchedLoweringOutcomes,
|
|
19085
19093
|
notes: sourceNotes(graph, target)
|
|
19086
19094
|
};
|
|
19087
19095
|
}
|
|
19088
19096
|
const asGenerated = items.filter((item) => item.outputPath === target || item.files.some((file) => joinOutputRoot2(item.outputRoot, file) === target));
|
|
19089
19097
|
if (asGenerated.length > 0) {
|
|
19098
|
+
const matchedLoweringOutcomes = explainLoweringOutcomes(target, asGenerated, loweringOutcomes, {
|
|
19099
|
+
includeSourcePaths: false
|
|
19100
|
+
});
|
|
19090
19101
|
return {
|
|
19091
19102
|
path: target,
|
|
19092
19103
|
kind: "generated",
|
|
19093
19104
|
entries: asGenerated.map((item) => item.entry),
|
|
19094
|
-
|
|
19095
|
-
|
|
19096
|
-
}),
|
|
19105
|
+
features: featureCapabilitiesForPath(graph, target, asGenerated, matchedLoweringOutcomes),
|
|
19106
|
+
loweringOutcomes: matchedLoweringOutcomes,
|
|
19097
19107
|
notes: [`Generated output; rebuild with skillset build, verify with skillset check.`]
|
|
19098
19108
|
};
|
|
19099
19109
|
}
|
|
19100
19110
|
const prefixMatch = items.filter((item) => item.sourcePath.startsWith(`${target}/`));
|
|
19101
19111
|
if (prefixMatch.length > 0) {
|
|
19112
|
+
const matchedLoweringOutcomes = explainLoweringOutcomes(target, prefixMatch, loweringOutcomes);
|
|
19102
19113
|
return {
|
|
19103
19114
|
path: target,
|
|
19104
19115
|
kind: "source-plugin",
|
|
19105
19116
|
entries: prefixMatch.map((item) => item.entry),
|
|
19106
|
-
|
|
19117
|
+
features: featureCapabilitiesForPath(graph, target, prefixMatch, matchedLoweringOutcomes),
|
|
19118
|
+
loweringOutcomes: matchedLoweringOutcomes,
|
|
19107
19119
|
notes: [`Matched ${prefixMatch.length} generated entries under this source path.`]
|
|
19108
19120
|
};
|
|
19109
19121
|
}
|
|
@@ -19113,6 +19125,7 @@ async function explainPath(rootPath, inputPath, options = {}) {
|
|
|
19113
19125
|
path: target,
|
|
19114
19126
|
kind: explainSourceKind(graph, target),
|
|
19115
19127
|
entries: [],
|
|
19128
|
+
features: featureCapabilitiesForPath(graph, target, [], sourceOnlyOutcomes),
|
|
19116
19129
|
loweringOutcomes: sourceOnlyOutcomes,
|
|
19117
19130
|
notes: [`Matched ${sourceOnlyOutcomes.length} lowering outcome(s) under this source path.`]
|
|
19118
19131
|
};
|
|
@@ -19121,6 +19134,7 @@ async function explainPath(rootPath, inputPath, options = {}) {
|
|
|
19121
19134
|
path: target,
|
|
19122
19135
|
kind: "unknown",
|
|
19123
19136
|
entries: [],
|
|
19137
|
+
features: [],
|
|
19124
19138
|
loweringOutcomes: [],
|
|
19125
19139
|
notes: [
|
|
19126
19140
|
`No lock entry references ${target}. Pass a source path under ${graph.sourceDir}/ or a generated output path.`
|
|
@@ -19132,6 +19146,21 @@ async function listGeneratedEntries(rootPath, options = {}) {
|
|
|
19132
19146
|
const rendered = scopedRenderedFiles(graph, await renderBuildGraph(graph), options.scopes);
|
|
19133
19147
|
return collectLockItems(rendered).map((item) => item.entry);
|
|
19134
19148
|
}
|
|
19149
|
+
function listFeatureCapabilities(featureId) {
|
|
19150
|
+
const features = featureId === undefined ? listSkillsetFeatures() : [getSkillsetFeature(featureId)].filter((feature2) => feature2 !== undefined);
|
|
19151
|
+
return features.map(featureCapability);
|
|
19152
|
+
}
|
|
19153
|
+
function summarizeFeatureCapabilities(features = listFeatureCapabilities()) {
|
|
19154
|
+
return {
|
|
19155
|
+
byFeatureStatus: countBy(features.map((feature2) => feature2.status)),
|
|
19156
|
+
byTargetSupport: {
|
|
19157
|
+
claude: countBy(features.map((feature2) => feature2.targetSupport.claude.status)),
|
|
19158
|
+
codex: countBy(features.map((feature2) => feature2.targetSupport.codex.status))
|
|
19159
|
+
},
|
|
19160
|
+
featureIds: features.map((feature2) => feature2.id).sort(compareStrings),
|
|
19161
|
+
total: features.length
|
|
19162
|
+
};
|
|
19163
|
+
}
|
|
19135
19164
|
async function doctorSkillset(rootPath, options = {}) {
|
|
19136
19165
|
let graph;
|
|
19137
19166
|
try {
|
|
@@ -19143,6 +19172,7 @@ async function doctorSkillset(rootPath, options = {}) {
|
|
|
19143
19172
|
buildError: errorMessage3(error),
|
|
19144
19173
|
buildDiagnostics: buildDiagnostics2,
|
|
19145
19174
|
drift: { added: [], changed: [], missing: [], removed: [] },
|
|
19175
|
+
featureCapabilities: summarizeFeatureCapabilities(),
|
|
19146
19176
|
lintIssues: [],
|
|
19147
19177
|
loweringOutcomes: loweringOutcomes2,
|
|
19148
19178
|
notableLoweringOutcomes: notableLoweringOutcomes(loweringOutcomes2),
|
|
@@ -19170,6 +19200,7 @@ async function doctorSkillset(rootPath, options = {}) {
|
|
|
19170
19200
|
...buildError === undefined ? {} : { buildError },
|
|
19171
19201
|
buildDiagnostics,
|
|
19172
19202
|
drift,
|
|
19203
|
+
featureCapabilities: summarizeFeatureCapabilities(),
|
|
19173
19204
|
lintIssues: lint.issues,
|
|
19174
19205
|
loweringOutcomes,
|
|
19175
19206
|
notableLoweringOutcomes: notable,
|
|
@@ -19230,7 +19261,7 @@ function collectLockItems(rendered) {
|
|
|
19230
19261
|
continue;
|
|
19231
19262
|
let parsed;
|
|
19232
19263
|
try {
|
|
19233
|
-
parsed = JSON.parse(
|
|
19264
|
+
parsed = JSON.parse(textDecoder5.decode(file.content));
|
|
19234
19265
|
} catch {
|
|
19235
19266
|
continue;
|
|
19236
19267
|
}
|
|
@@ -19331,6 +19362,82 @@ function sourceNotes(graph, target) {
|
|
|
19331
19362
|
}
|
|
19332
19363
|
return notes;
|
|
19333
19364
|
}
|
|
19365
|
+
function featureCapabilitiesForPath(graph, target, items, outcomes) {
|
|
19366
|
+
const featureIds = new Set;
|
|
19367
|
+
for (const item of items) {
|
|
19368
|
+
if (item.entry.feature !== undefined)
|
|
19369
|
+
featureIds.add(item.entry.feature);
|
|
19370
|
+
}
|
|
19371
|
+
for (const outcome of outcomes) {
|
|
19372
|
+
featureIds.add(outcome.featureId);
|
|
19373
|
+
}
|
|
19374
|
+
for (const featureId of inferredFeatureIdsForSourcePath(graph, target)) {
|
|
19375
|
+
featureIds.add(featureId);
|
|
19376
|
+
}
|
|
19377
|
+
return [...featureIds].map((featureId) => getSkillsetFeature(featureId)).filter((feature2) => feature2 !== undefined).map(featureCapability).sort((left, right) => compareStrings(left.id, right.id));
|
|
19378
|
+
}
|
|
19379
|
+
function inferredFeatureIdsForSourcePath(graph, target) {
|
|
19380
|
+
const featureIds = [];
|
|
19381
|
+
if (graph.rules.some((rule) => relative15(graph.rootPath, rule.sourcePath) === target)) {
|
|
19382
|
+
featureIds.push("project-instructions");
|
|
19383
|
+
}
|
|
19384
|
+
if (graph.projectAgents.some((agent) => relative15(graph.rootPath, agent.sourcePath) === target)) {
|
|
19385
|
+
featureIds.push("project-agents");
|
|
19386
|
+
}
|
|
19387
|
+
if (graph.projectIslands.some((island) => pathMatchesSource(graph, target, island.sourcePath))) {
|
|
19388
|
+
featureIds.push("target-native-islands");
|
|
19389
|
+
}
|
|
19390
|
+
for (const skill of graph.standaloneSkills) {
|
|
19391
|
+
if (!pathMatchesSource(graph, target, skill.sourcePath))
|
|
19392
|
+
continue;
|
|
19393
|
+
featureIds.push("standalone-skills");
|
|
19394
|
+
if (skill.resources.length > 0)
|
|
19395
|
+
featureIds.push("resources");
|
|
19396
|
+
}
|
|
19397
|
+
for (const plugin of graph.plugins) {
|
|
19398
|
+
if (pathMatchesSource(graph, target, plugin.configPath)) {
|
|
19399
|
+
featureIds.push("plugin-manifests");
|
|
19400
|
+
}
|
|
19401
|
+
for (const skill of plugin.skills) {
|
|
19402
|
+
if (!pathMatchesSource(graph, target, skill.sourcePath))
|
|
19403
|
+
continue;
|
|
19404
|
+
featureIds.push("plugin-skills");
|
|
19405
|
+
if (skill.resources.length > 0)
|
|
19406
|
+
featureIds.push("resources");
|
|
19407
|
+
}
|
|
19408
|
+
}
|
|
19409
|
+
return featureIds;
|
|
19410
|
+
}
|
|
19411
|
+
function pathMatchesSource(graph, target, sourcePath) {
|
|
19412
|
+
const relativePath2 = relative15(graph.rootPath, sourcePath).replaceAll("\\", "/");
|
|
19413
|
+
return target === relativePath2 || target.startsWith(`${relativePath2}/`);
|
|
19414
|
+
}
|
|
19415
|
+
function featureCapability(feature2) {
|
|
19416
|
+
return {
|
|
19417
|
+
docs: feature2.docs,
|
|
19418
|
+
id: feature2.id,
|
|
19419
|
+
status: feature2.status,
|
|
19420
|
+
targetSupport: {
|
|
19421
|
+
claude: supportCapability(feature2.targetSupport.claude),
|
|
19422
|
+
codex: supportCapability(feature2.targetSupport.codex)
|
|
19423
|
+
},
|
|
19424
|
+
title: feature2.title
|
|
19425
|
+
};
|
|
19426
|
+
}
|
|
19427
|
+
function supportCapability(support) {
|
|
19428
|
+
return {
|
|
19429
|
+
...support.note === undefined ? {} : { note: support.note },
|
|
19430
|
+
...support.reason === undefined ? {} : { reason: support.reason },
|
|
19431
|
+
status: support.status
|
|
19432
|
+
};
|
|
19433
|
+
}
|
|
19434
|
+
function countBy(values) {
|
|
19435
|
+
const counts = {};
|
|
19436
|
+
for (const value of [...values].sort(compareStrings)) {
|
|
19437
|
+
counts[value] = (counts[value] ?? 0) + 1;
|
|
19438
|
+
}
|
|
19439
|
+
return counts;
|
|
19440
|
+
}
|
|
19334
19441
|
function normalizeRepoPath(rootPath, inputPath) {
|
|
19335
19442
|
const absolute = resolve8(rootPath, inputPath);
|
|
19336
19443
|
return relative15(rootPath, absolute).replaceAll("\\", "/");
|
|
@@ -20632,6 +20739,7 @@ var USAGE = [
|
|
|
20632
20739
|
" skillset release apply [--yes|--dry-run] [--root <path>] [--source <dir>] [--dist <dir>]",
|
|
20633
20740
|
" skillset restore <backup-id> [--yes|--dry-run] [--root <path>]",
|
|
20634
20741
|
" skillset distribute plan [name] [--root <path>] [--source <dir>] [--dist <dir>]",
|
|
20742
|
+
" skillset features [feature-id] [--json]",
|
|
20635
20743
|
" skillset test [name] [--root <path>] [--source <dir>]",
|
|
20636
20744
|
" skillset hooks print --runner <lefthook|husky|pre-commit|git> [--pre-commit] [--pre-push]",
|
|
20637
20745
|
" skillset hooks print --target <claude|codex> --agent-runtime",
|
|
@@ -20965,6 +21073,25 @@ async function runCli(rawArgs = process.argv.slice(2), invokedName = basename8(p
|
|
|
20965
21073
|
console.log(`skillset: listed ${entries.length} generated entries`);
|
|
20966
21074
|
return;
|
|
20967
21075
|
}
|
|
21076
|
+
if (command === "features") {
|
|
21077
|
+
const features = listFeatureCapabilities(importPath);
|
|
21078
|
+
if (jsonOutput) {
|
|
21079
|
+
process.stdout.write(renderValidatedJson({ features }, "skillset features"));
|
|
21080
|
+
if (importPath !== undefined && features.length === 0)
|
|
21081
|
+
process.exitCode = 1;
|
|
21082
|
+
return;
|
|
21083
|
+
}
|
|
21084
|
+
if (features.length === 0) {
|
|
21085
|
+
console.log(`skillset: feature ${importPath ?? ""} not found`);
|
|
21086
|
+
process.exitCode = 1;
|
|
21087
|
+
return;
|
|
21088
|
+
}
|
|
21089
|
+
for (const feature2 of features) {
|
|
21090
|
+
printFeatureCapability(feature2);
|
|
21091
|
+
}
|
|
21092
|
+
console.log(`skillset: listed ${features.length} feature${features.length === 1 ? "" : "s"}`);
|
|
21093
|
+
return;
|
|
21094
|
+
}
|
|
20968
21095
|
if (command === "explain") {
|
|
20969
21096
|
if (importPath === undefined) {
|
|
20970
21097
|
throw new Error("skillset: expected a path to explain");
|
|
@@ -21007,6 +21134,11 @@ async function runCli(rawArgs = process.argv.slice(2), invokedName = basename8(p
|
|
|
21007
21134
|
if (entry.outputHash !== undefined)
|
|
21008
21135
|
console.log(` output hash: ${entry.outputHash}`);
|
|
21009
21136
|
}
|
|
21137
|
+
for (const feature2 of result3.features) {
|
|
21138
|
+
console.log(` feature ${feature2.id}: ${feature2.title}`);
|
|
21139
|
+
console.log(` claude: ${feature2.targetSupport.claude.status}`);
|
|
21140
|
+
console.log(` codex: ${feature2.targetSupport.codex.status}`);
|
|
21141
|
+
}
|
|
21010
21142
|
for (const outcome of result3.loweringOutcomes) {
|
|
21011
21143
|
printLoweringOutcome(outcome);
|
|
21012
21144
|
}
|
|
@@ -21036,6 +21168,9 @@ async function runCli(rawArgs = process.argv.slice(2), invokedName = basename8(p
|
|
|
21036
21168
|
if (driftCount > 0) {
|
|
21037
21169
|
console.log(` drift: ${added.length} added, ${changed.length} changed, ${missing.length} missing, ${removed.length} removed (run skillset build --yes)`);
|
|
21038
21170
|
}
|
|
21171
|
+
console.log(` features: ${report.featureCapabilities.total} registry entries; status ${formatCountSummary(report.featureCapabilities.byFeatureStatus)}`);
|
|
21172
|
+
console.log(` feature support: claude ${formatCountSummary(report.featureCapabilities.byTargetSupport.claude)}`);
|
|
21173
|
+
console.log(` feature support: codex ${formatCountSummary(report.featureCapabilities.byTargetSupport.codex)}`);
|
|
21039
21174
|
for (const outcome of report.notableLoweringOutcomes) {
|
|
21040
21175
|
printLoweringOutcome(outcome);
|
|
21041
21176
|
}
|
|
@@ -21395,6 +21530,22 @@ function printSkillsetTest(report) {
|
|
|
21395
21530
|
if (report.activationPath !== undefined)
|
|
21396
21531
|
console.log(` activation: ${report.activationPath}`);
|
|
21397
21532
|
}
|
|
21533
|
+
function printFeatureCapability(feature2) {
|
|
21534
|
+
console.log(`feature ${feature2.id}: ${feature2.title}`);
|
|
21535
|
+
console.log(` status: ${feature2.status}`);
|
|
21536
|
+
console.log(` claude: ${formatFeatureSupport(feature2.targetSupport.claude)}`);
|
|
21537
|
+
console.log(` codex: ${formatFeatureSupport(feature2.targetSupport.codex)}`);
|
|
21538
|
+
if (feature2.docs.length > 0)
|
|
21539
|
+
console.log(` docs: ${feature2.docs.join(", ")}`);
|
|
21540
|
+
}
|
|
21541
|
+
function formatFeatureSupport(support) {
|
|
21542
|
+
const reason = support.reason === undefined ? "" : ` (${support.reason})`;
|
|
21543
|
+
const note = support.note === undefined ? "" : ` note: ${support.note}`;
|
|
21544
|
+
return `${support.status}${reason}${note}`;
|
|
21545
|
+
}
|
|
21546
|
+
function formatCountSummary(counts) {
|
|
21547
|
+
return Object.entries(counts).sort(([left], [right]) => left.localeCompare(right)).map(([key, count]) => `${key} ${count}`).join(", ");
|
|
21548
|
+
}
|
|
21398
21549
|
function printLoweringOutcome(outcome) {
|
|
21399
21550
|
const target = outcome.target ?? "workspace";
|
|
21400
21551
|
const policy = outcome.policy === undefined ? "" : ` policy: ${outcome.policy}`;
|
|
@@ -21409,8 +21560,8 @@ function printLoweringOutcome(outcome) {
|
|
|
21409
21560
|
}
|
|
21410
21561
|
function parseArgs(args) {
|
|
21411
21562
|
const command = args[0];
|
|
21412
|
-
if (command !== "adopt" && command !== "build" && command !== "change" && command !== "check" && command !== "ci" && command !== "create" && command !== "diff" && command !== "distribute" && command !== "doctor" && command !== "explain" && command !== "hooks" && command !== "import" && command !== "init" && command !== "lint" && command !== "list" && command !== "release" && command !== "restore" && command !== "test") {
|
|
21413
|
-
throw new Error(`skillset: expected command adopt, build, change, check, ci, create, diff, distribute, doctor, explain, hooks, import, init, lint, list, release, restore, or test
|
|
21563
|
+
if (command !== "adopt" && command !== "build" && command !== "change" && command !== "check" && command !== "ci" && command !== "create" && command !== "diff" && command !== "distribute" && command !== "doctor" && command !== "explain" && command !== "features" && command !== "hooks" && command !== "import" && command !== "init" && command !== "lint" && command !== "list" && command !== "release" && command !== "restore" && command !== "test") {
|
|
21564
|
+
throw new Error(`skillset: expected command adopt, build, change, check, ci, create, diff, distribute, doctor, explain, features, hooks, import, init, lint, list, release, restore, or test
|
|
21414
21565
|
` + USAGE);
|
|
21415
21566
|
}
|
|
21416
21567
|
let changeSubcommand;
|
|
@@ -21534,6 +21685,13 @@ function parseArgs(args) {
|
|
|
21534
21685
|
importPath = rawPath;
|
|
21535
21686
|
index += 1;
|
|
21536
21687
|
}
|
|
21688
|
+
if (command === "features") {
|
|
21689
|
+
const rawFeatureId = args[index];
|
|
21690
|
+
if (rawFeatureId !== undefined && !rawFeatureId.startsWith("--")) {
|
|
21691
|
+
importPath = rawFeatureId;
|
|
21692
|
+
index += 1;
|
|
21693
|
+
}
|
|
21694
|
+
}
|
|
21537
21695
|
if (command === "restore") {
|
|
21538
21696
|
const rawBackupId = args[index];
|
|
21539
21697
|
if (rawBackupId === undefined || rawBackupId.startsWith("--")) {
|
|
@@ -21989,9 +22147,9 @@ function validateAdoptFlags(command, adopt) {
|
|
|
21989
22147
|
function validateJsonFlags(command, jsonOutput) {
|
|
21990
22148
|
if (!jsonOutput)
|
|
21991
22149
|
return;
|
|
21992
|
-
if (command === "doctor" || command === "explain")
|
|
22150
|
+
if (command === "doctor" || command === "explain" || command === "features")
|
|
21993
22151
|
return;
|
|
21994
|
-
throw new Error("skillset: --json is only supported with doctor or
|
|
22152
|
+
throw new Error("skillset: --json is only supported with doctor, explain, or features");
|
|
21995
22153
|
}
|
|
21996
22154
|
function isImportKind(value) {
|
|
21997
22155
|
return value === "skill" || value === "skills" || value === "plugin" || value === "plugins";
|
package/dist/create.js
CHANGED
|
@@ -7517,12 +7517,12 @@ var skillsetFeatureRegistry = defineFeatureRegistry([
|
|
|
7517
7517
|
status: "externally_managed"
|
|
7518
7518
|
},
|
|
7519
7519
|
cursor: {
|
|
7520
|
-
evidence: [docs("docs/features/runtime-adapters.md"), fixture("fixtures/external/repos
|
|
7520
|
+
evidence: [docs("docs/features/runtime-adapters.md"), fixture("fixtures/external/repos.yaml")],
|
|
7521
7521
|
reason: "Cursor support needs target documentation and adapter evidence before Skillset can lower or distribute it.",
|
|
7522
7522
|
status: "planned"
|
|
7523
7523
|
},
|
|
7524
7524
|
"gemini-cli": {
|
|
7525
|
-
evidence: [docs("docs/features/runtime-adapters.md"), fixture("fixtures/external/repos
|
|
7525
|
+
evidence: [docs("docs/features/runtime-adapters.md"), fixture("fixtures/external/repos.yaml")],
|
|
7526
7526
|
reason: "Gemini support needs target documentation and adapter evidence before Skillset can lower or distribute it.",
|
|
7527
7527
|
status: "planned"
|
|
7528
7528
|
},
|
|
@@ -7537,7 +7537,7 @@ var skillsetFeatureRegistry = defineFeatureRegistry([
|
|
|
7537
7537
|
status: "future"
|
|
7538
7538
|
},
|
|
7539
7539
|
opencode: {
|
|
7540
|
-
evidence: [docs("docs/features/runtime-adapters.md"), fixture("fixtures/external/repos
|
|
7540
|
+
evidence: [docs("docs/features/runtime-adapters.md"), fixture("fixtures/external/repos.yaml")],
|
|
7541
7541
|
reason: "OpenCode support needs target documentation and adapter evidence before Skillset can lower or distribute it.",
|
|
7542
7542
|
status: "planned"
|
|
7543
7543
|
}
|
|
@@ -7624,7 +7624,7 @@ var skillsetFeatureRegistry = defineFeatureRegistry([
|
|
|
7624
7624
|
status: "implemented",
|
|
7625
7625
|
summary: "Normalizes tool policy intent into Claude allowed-tools fields and Codex metadata sidecars.",
|
|
7626
7626
|
targetSupport: {
|
|
7627
|
-
claude: { status: "
|
|
7627
|
+
claude: { status: "transformed" },
|
|
7628
7628
|
codex: { status: "metadata_only" }
|
|
7629
7629
|
},
|
|
7630
7630
|
title: "Tool Intent",
|
|
@@ -7679,6 +7679,9 @@ function defineFeatureRegistry(entries) {
|
|
|
7679
7679
|
assertRuntimeSupportVocabulary(entries);
|
|
7680
7680
|
return [...entries].sort((left, right) => compareStrings(left.id, right.id));
|
|
7681
7681
|
}
|
|
7682
|
+
function listSkillsetFeatures(registry = skillsetFeatureRegistry) {
|
|
7683
|
+
return registry;
|
|
7684
|
+
}
|
|
7682
7685
|
function getSkillsetFeature(id, registry = skillsetFeatureRegistry) {
|
|
7683
7686
|
return registry.find((entry) => entry.id === id);
|
|
7684
7687
|
}
|
|
@@ -14447,6 +14450,9 @@ async function exists6(path) {
|
|
|
14447
14450
|
throw error;
|
|
14448
14451
|
}
|
|
14449
14452
|
}
|
|
14453
|
+
// packages/core/src/host-leak.ts
|
|
14454
|
+
var textDecoder3 = new TextDecoder;
|
|
14455
|
+
|
|
14450
14456
|
// packages/core/src/normalized-output-tree.ts
|
|
14451
14457
|
var DEFAULT_STRUCTURED_JSON_BASENAMES = new Set([".skillset.lock"]);
|
|
14452
14458
|
|
|
@@ -14454,7 +14460,7 @@ var DEFAULT_STRUCTURED_JSON_BASENAMES = new Set([".skillset.lock"]);
|
|
|
14454
14460
|
var textEncoder4 = new TextEncoder;
|
|
14455
14461
|
// packages/core/src/destination-ownership.ts
|
|
14456
14462
|
import { basename as basename3 } from "path";
|
|
14457
|
-
var
|
|
14463
|
+
var textDecoder4 = new TextDecoder;
|
|
14458
14464
|
function classifyDestinationOwnership(args) {
|
|
14459
14465
|
const file = classifyFileOwnership(args.path, args.target);
|
|
14460
14466
|
const fields = args.content === undefined ? [] : classifyFieldOwnership(args.path, args.target, args.content);
|
|
@@ -14493,7 +14499,7 @@ function classifyFieldOwnership(path, target, content) {
|
|
|
14493
14499
|
return [];
|
|
14494
14500
|
let record;
|
|
14495
14501
|
try {
|
|
14496
|
-
const parsed = JSON.parse(
|
|
14502
|
+
const parsed = JSON.parse(textDecoder4.decode(content));
|
|
14497
14503
|
if (!isJsonRecord(parsed))
|
|
14498
14504
|
return [];
|
|
14499
14505
|
record = parsed;
|
|
@@ -19064,7 +19070,7 @@ async function exists12(path2) {
|
|
|
19064
19070
|
|
|
19065
19071
|
// apps/skillset/src/authoring.ts
|
|
19066
19072
|
import { resolve as resolve8, relative as relative15 } from "path";
|
|
19067
|
-
var
|
|
19073
|
+
var textDecoder5 = new TextDecoder;
|
|
19068
19074
|
async function explainPath(rootPath, inputPath, options = {}) {
|
|
19069
19075
|
const graph = await loadBuildGraph(rootPath, options);
|
|
19070
19076
|
const allRendered = await renderBuildGraph(graph);
|
|
@@ -19077,33 +19083,39 @@ async function explainPath(rootPath, inputPath, options = {}) {
|
|
|
19077
19083
|
const items = collectLockItems(rendered);
|
|
19078
19084
|
const asSource = items.filter((item) => item.sourcePath === target);
|
|
19079
19085
|
if (asSource.length > 0) {
|
|
19086
|
+
const matchedLoweringOutcomes = explainLoweringOutcomes(target, asSource, loweringOutcomes);
|
|
19080
19087
|
return {
|
|
19081
19088
|
path: target,
|
|
19082
19089
|
kind: explainSourceKind(graph, target),
|
|
19083
19090
|
entries: asSource.map((item) => item.entry),
|
|
19084
|
-
|
|
19091
|
+
features: featureCapabilitiesForPath(graph, target, asSource, matchedLoweringOutcomes),
|
|
19092
|
+
loweringOutcomes: matchedLoweringOutcomes,
|
|
19085
19093
|
notes: sourceNotes(graph, target)
|
|
19086
19094
|
};
|
|
19087
19095
|
}
|
|
19088
19096
|
const asGenerated = items.filter((item) => item.outputPath === target || item.files.some((file) => joinOutputRoot2(item.outputRoot, file) === target));
|
|
19089
19097
|
if (asGenerated.length > 0) {
|
|
19098
|
+
const matchedLoweringOutcomes = explainLoweringOutcomes(target, asGenerated, loweringOutcomes, {
|
|
19099
|
+
includeSourcePaths: false
|
|
19100
|
+
});
|
|
19090
19101
|
return {
|
|
19091
19102
|
path: target,
|
|
19092
19103
|
kind: "generated",
|
|
19093
19104
|
entries: asGenerated.map((item) => item.entry),
|
|
19094
|
-
|
|
19095
|
-
|
|
19096
|
-
}),
|
|
19105
|
+
features: featureCapabilitiesForPath(graph, target, asGenerated, matchedLoweringOutcomes),
|
|
19106
|
+
loweringOutcomes: matchedLoweringOutcomes,
|
|
19097
19107
|
notes: [`Generated output; rebuild with skillset build, verify with skillset check.`]
|
|
19098
19108
|
};
|
|
19099
19109
|
}
|
|
19100
19110
|
const prefixMatch = items.filter((item) => item.sourcePath.startsWith(`${target}/`));
|
|
19101
19111
|
if (prefixMatch.length > 0) {
|
|
19112
|
+
const matchedLoweringOutcomes = explainLoweringOutcomes(target, prefixMatch, loweringOutcomes);
|
|
19102
19113
|
return {
|
|
19103
19114
|
path: target,
|
|
19104
19115
|
kind: "source-plugin",
|
|
19105
19116
|
entries: prefixMatch.map((item) => item.entry),
|
|
19106
|
-
|
|
19117
|
+
features: featureCapabilitiesForPath(graph, target, prefixMatch, matchedLoweringOutcomes),
|
|
19118
|
+
loweringOutcomes: matchedLoweringOutcomes,
|
|
19107
19119
|
notes: [`Matched ${prefixMatch.length} generated entries under this source path.`]
|
|
19108
19120
|
};
|
|
19109
19121
|
}
|
|
@@ -19113,6 +19125,7 @@ async function explainPath(rootPath, inputPath, options = {}) {
|
|
|
19113
19125
|
path: target,
|
|
19114
19126
|
kind: explainSourceKind(graph, target),
|
|
19115
19127
|
entries: [],
|
|
19128
|
+
features: featureCapabilitiesForPath(graph, target, [], sourceOnlyOutcomes),
|
|
19116
19129
|
loweringOutcomes: sourceOnlyOutcomes,
|
|
19117
19130
|
notes: [`Matched ${sourceOnlyOutcomes.length} lowering outcome(s) under this source path.`]
|
|
19118
19131
|
};
|
|
@@ -19121,6 +19134,7 @@ async function explainPath(rootPath, inputPath, options = {}) {
|
|
|
19121
19134
|
path: target,
|
|
19122
19135
|
kind: "unknown",
|
|
19123
19136
|
entries: [],
|
|
19137
|
+
features: [],
|
|
19124
19138
|
loweringOutcomes: [],
|
|
19125
19139
|
notes: [
|
|
19126
19140
|
`No lock entry references ${target}. Pass a source path under ${graph.sourceDir}/ or a generated output path.`
|
|
@@ -19132,6 +19146,21 @@ async function listGeneratedEntries(rootPath, options = {}) {
|
|
|
19132
19146
|
const rendered = scopedRenderedFiles(graph, await renderBuildGraph(graph), options.scopes);
|
|
19133
19147
|
return collectLockItems(rendered).map((item) => item.entry);
|
|
19134
19148
|
}
|
|
19149
|
+
function listFeatureCapabilities(featureId) {
|
|
19150
|
+
const features = featureId === undefined ? listSkillsetFeatures() : [getSkillsetFeature(featureId)].filter((feature2) => feature2 !== undefined);
|
|
19151
|
+
return features.map(featureCapability);
|
|
19152
|
+
}
|
|
19153
|
+
function summarizeFeatureCapabilities(features = listFeatureCapabilities()) {
|
|
19154
|
+
return {
|
|
19155
|
+
byFeatureStatus: countBy(features.map((feature2) => feature2.status)),
|
|
19156
|
+
byTargetSupport: {
|
|
19157
|
+
claude: countBy(features.map((feature2) => feature2.targetSupport.claude.status)),
|
|
19158
|
+
codex: countBy(features.map((feature2) => feature2.targetSupport.codex.status))
|
|
19159
|
+
},
|
|
19160
|
+
featureIds: features.map((feature2) => feature2.id).sort(compareStrings),
|
|
19161
|
+
total: features.length
|
|
19162
|
+
};
|
|
19163
|
+
}
|
|
19135
19164
|
async function doctorSkillset(rootPath, options = {}) {
|
|
19136
19165
|
let graph;
|
|
19137
19166
|
try {
|
|
@@ -19143,6 +19172,7 @@ async function doctorSkillset(rootPath, options = {}) {
|
|
|
19143
19172
|
buildError: errorMessage3(error),
|
|
19144
19173
|
buildDiagnostics: buildDiagnostics2,
|
|
19145
19174
|
drift: { added: [], changed: [], missing: [], removed: [] },
|
|
19175
|
+
featureCapabilities: summarizeFeatureCapabilities(),
|
|
19146
19176
|
lintIssues: [],
|
|
19147
19177
|
loweringOutcomes: loweringOutcomes2,
|
|
19148
19178
|
notableLoweringOutcomes: notableLoweringOutcomes(loweringOutcomes2),
|
|
@@ -19170,6 +19200,7 @@ async function doctorSkillset(rootPath, options = {}) {
|
|
|
19170
19200
|
...buildError === undefined ? {} : { buildError },
|
|
19171
19201
|
buildDiagnostics,
|
|
19172
19202
|
drift,
|
|
19203
|
+
featureCapabilities: summarizeFeatureCapabilities(),
|
|
19173
19204
|
lintIssues: lint.issues,
|
|
19174
19205
|
loweringOutcomes,
|
|
19175
19206
|
notableLoweringOutcomes: notable,
|
|
@@ -19230,7 +19261,7 @@ function collectLockItems(rendered) {
|
|
|
19230
19261
|
continue;
|
|
19231
19262
|
let parsed;
|
|
19232
19263
|
try {
|
|
19233
|
-
parsed = JSON.parse(
|
|
19264
|
+
parsed = JSON.parse(textDecoder5.decode(file.content));
|
|
19234
19265
|
} catch {
|
|
19235
19266
|
continue;
|
|
19236
19267
|
}
|
|
@@ -19331,6 +19362,82 @@ function sourceNotes(graph, target) {
|
|
|
19331
19362
|
}
|
|
19332
19363
|
return notes;
|
|
19333
19364
|
}
|
|
19365
|
+
function featureCapabilitiesForPath(graph, target, items, outcomes) {
|
|
19366
|
+
const featureIds = new Set;
|
|
19367
|
+
for (const item of items) {
|
|
19368
|
+
if (item.entry.feature !== undefined)
|
|
19369
|
+
featureIds.add(item.entry.feature);
|
|
19370
|
+
}
|
|
19371
|
+
for (const outcome of outcomes) {
|
|
19372
|
+
featureIds.add(outcome.featureId);
|
|
19373
|
+
}
|
|
19374
|
+
for (const featureId of inferredFeatureIdsForSourcePath(graph, target)) {
|
|
19375
|
+
featureIds.add(featureId);
|
|
19376
|
+
}
|
|
19377
|
+
return [...featureIds].map((featureId) => getSkillsetFeature(featureId)).filter((feature2) => feature2 !== undefined).map(featureCapability).sort((left, right) => compareStrings(left.id, right.id));
|
|
19378
|
+
}
|
|
19379
|
+
function inferredFeatureIdsForSourcePath(graph, target) {
|
|
19380
|
+
const featureIds = [];
|
|
19381
|
+
if (graph.rules.some((rule) => relative15(graph.rootPath, rule.sourcePath) === target)) {
|
|
19382
|
+
featureIds.push("project-instructions");
|
|
19383
|
+
}
|
|
19384
|
+
if (graph.projectAgents.some((agent) => relative15(graph.rootPath, agent.sourcePath) === target)) {
|
|
19385
|
+
featureIds.push("project-agents");
|
|
19386
|
+
}
|
|
19387
|
+
if (graph.projectIslands.some((island) => pathMatchesSource(graph, target, island.sourcePath))) {
|
|
19388
|
+
featureIds.push("target-native-islands");
|
|
19389
|
+
}
|
|
19390
|
+
for (const skill of graph.standaloneSkills) {
|
|
19391
|
+
if (!pathMatchesSource(graph, target, skill.sourcePath))
|
|
19392
|
+
continue;
|
|
19393
|
+
featureIds.push("standalone-skills");
|
|
19394
|
+
if (skill.resources.length > 0)
|
|
19395
|
+
featureIds.push("resources");
|
|
19396
|
+
}
|
|
19397
|
+
for (const plugin of graph.plugins) {
|
|
19398
|
+
if (pathMatchesSource(graph, target, plugin.configPath)) {
|
|
19399
|
+
featureIds.push("plugin-manifests");
|
|
19400
|
+
}
|
|
19401
|
+
for (const skill of plugin.skills) {
|
|
19402
|
+
if (!pathMatchesSource(graph, target, skill.sourcePath))
|
|
19403
|
+
continue;
|
|
19404
|
+
featureIds.push("plugin-skills");
|
|
19405
|
+
if (skill.resources.length > 0)
|
|
19406
|
+
featureIds.push("resources");
|
|
19407
|
+
}
|
|
19408
|
+
}
|
|
19409
|
+
return featureIds;
|
|
19410
|
+
}
|
|
19411
|
+
function pathMatchesSource(graph, target, sourcePath) {
|
|
19412
|
+
const relativePath2 = relative15(graph.rootPath, sourcePath).replaceAll("\\", "/");
|
|
19413
|
+
return target === relativePath2 || target.startsWith(`${relativePath2}/`);
|
|
19414
|
+
}
|
|
19415
|
+
function featureCapability(feature2) {
|
|
19416
|
+
return {
|
|
19417
|
+
docs: feature2.docs,
|
|
19418
|
+
id: feature2.id,
|
|
19419
|
+
status: feature2.status,
|
|
19420
|
+
targetSupport: {
|
|
19421
|
+
claude: supportCapability(feature2.targetSupport.claude),
|
|
19422
|
+
codex: supportCapability(feature2.targetSupport.codex)
|
|
19423
|
+
},
|
|
19424
|
+
title: feature2.title
|
|
19425
|
+
};
|
|
19426
|
+
}
|
|
19427
|
+
function supportCapability(support) {
|
|
19428
|
+
return {
|
|
19429
|
+
...support.note === undefined ? {} : { note: support.note },
|
|
19430
|
+
...support.reason === undefined ? {} : { reason: support.reason },
|
|
19431
|
+
status: support.status
|
|
19432
|
+
};
|
|
19433
|
+
}
|
|
19434
|
+
function countBy(values) {
|
|
19435
|
+
const counts = {};
|
|
19436
|
+
for (const value of [...values].sort(compareStrings)) {
|
|
19437
|
+
counts[value] = (counts[value] ?? 0) + 1;
|
|
19438
|
+
}
|
|
19439
|
+
return counts;
|
|
19440
|
+
}
|
|
19334
19441
|
function normalizeRepoPath(rootPath, inputPath) {
|
|
19335
19442
|
const absolute = resolve8(rootPath, inputPath);
|
|
19336
19443
|
return relative15(rootPath, absolute).replaceAll("\\", "/");
|
|
@@ -20632,6 +20739,7 @@ var USAGE = [
|
|
|
20632
20739
|
" skillset release apply [--yes|--dry-run] [--root <path>] [--source <dir>] [--dist <dir>]",
|
|
20633
20740
|
" skillset restore <backup-id> [--yes|--dry-run] [--root <path>]",
|
|
20634
20741
|
" skillset distribute plan [name] [--root <path>] [--source <dir>] [--dist <dir>]",
|
|
20742
|
+
" skillset features [feature-id] [--json]",
|
|
20635
20743
|
" skillset test [name] [--root <path>] [--source <dir>]",
|
|
20636
20744
|
" skillset hooks print --runner <lefthook|husky|pre-commit|git> [--pre-commit] [--pre-push]",
|
|
20637
20745
|
" skillset hooks print --target <claude|codex> --agent-runtime",
|
|
@@ -20965,6 +21073,25 @@ async function runCli(rawArgs = process.argv.slice(2), invokedName = basename8(p
|
|
|
20965
21073
|
console.log(`skillset: listed ${entries.length} generated entries`);
|
|
20966
21074
|
return;
|
|
20967
21075
|
}
|
|
21076
|
+
if (command === "features") {
|
|
21077
|
+
const features = listFeatureCapabilities(importPath);
|
|
21078
|
+
if (jsonOutput) {
|
|
21079
|
+
process.stdout.write(renderValidatedJson({ features }, "skillset features"));
|
|
21080
|
+
if (importPath !== undefined && features.length === 0)
|
|
21081
|
+
process.exitCode = 1;
|
|
21082
|
+
return;
|
|
21083
|
+
}
|
|
21084
|
+
if (features.length === 0) {
|
|
21085
|
+
console.log(`skillset: feature ${importPath ?? ""} not found`);
|
|
21086
|
+
process.exitCode = 1;
|
|
21087
|
+
return;
|
|
21088
|
+
}
|
|
21089
|
+
for (const feature2 of features) {
|
|
21090
|
+
printFeatureCapability(feature2);
|
|
21091
|
+
}
|
|
21092
|
+
console.log(`skillset: listed ${features.length} feature${features.length === 1 ? "" : "s"}`);
|
|
21093
|
+
return;
|
|
21094
|
+
}
|
|
20968
21095
|
if (command === "explain") {
|
|
20969
21096
|
if (importPath === undefined) {
|
|
20970
21097
|
throw new Error("skillset: expected a path to explain");
|
|
@@ -21007,6 +21134,11 @@ async function runCli(rawArgs = process.argv.slice(2), invokedName = basename8(p
|
|
|
21007
21134
|
if (entry.outputHash !== undefined)
|
|
21008
21135
|
console.log(` output hash: ${entry.outputHash}`);
|
|
21009
21136
|
}
|
|
21137
|
+
for (const feature2 of result3.features) {
|
|
21138
|
+
console.log(` feature ${feature2.id}: ${feature2.title}`);
|
|
21139
|
+
console.log(` claude: ${feature2.targetSupport.claude.status}`);
|
|
21140
|
+
console.log(` codex: ${feature2.targetSupport.codex.status}`);
|
|
21141
|
+
}
|
|
21010
21142
|
for (const outcome of result3.loweringOutcomes) {
|
|
21011
21143
|
printLoweringOutcome(outcome);
|
|
21012
21144
|
}
|
|
@@ -21036,6 +21168,9 @@ async function runCli(rawArgs = process.argv.slice(2), invokedName = basename8(p
|
|
|
21036
21168
|
if (driftCount > 0) {
|
|
21037
21169
|
console.log(` drift: ${added.length} added, ${changed.length} changed, ${missing.length} missing, ${removed.length} removed (run skillset build --yes)`);
|
|
21038
21170
|
}
|
|
21171
|
+
console.log(` features: ${report.featureCapabilities.total} registry entries; status ${formatCountSummary(report.featureCapabilities.byFeatureStatus)}`);
|
|
21172
|
+
console.log(` feature support: claude ${formatCountSummary(report.featureCapabilities.byTargetSupport.claude)}`);
|
|
21173
|
+
console.log(` feature support: codex ${formatCountSummary(report.featureCapabilities.byTargetSupport.codex)}`);
|
|
21039
21174
|
for (const outcome of report.notableLoweringOutcomes) {
|
|
21040
21175
|
printLoweringOutcome(outcome);
|
|
21041
21176
|
}
|
|
@@ -21395,6 +21530,22 @@ function printSkillsetTest(report) {
|
|
|
21395
21530
|
if (report.activationPath !== undefined)
|
|
21396
21531
|
console.log(` activation: ${report.activationPath}`);
|
|
21397
21532
|
}
|
|
21533
|
+
function printFeatureCapability(feature2) {
|
|
21534
|
+
console.log(`feature ${feature2.id}: ${feature2.title}`);
|
|
21535
|
+
console.log(` status: ${feature2.status}`);
|
|
21536
|
+
console.log(` claude: ${formatFeatureSupport(feature2.targetSupport.claude)}`);
|
|
21537
|
+
console.log(` codex: ${formatFeatureSupport(feature2.targetSupport.codex)}`);
|
|
21538
|
+
if (feature2.docs.length > 0)
|
|
21539
|
+
console.log(` docs: ${feature2.docs.join(", ")}`);
|
|
21540
|
+
}
|
|
21541
|
+
function formatFeatureSupport(support) {
|
|
21542
|
+
const reason = support.reason === undefined ? "" : ` (${support.reason})`;
|
|
21543
|
+
const note = support.note === undefined ? "" : ` note: ${support.note}`;
|
|
21544
|
+
return `${support.status}${reason}${note}`;
|
|
21545
|
+
}
|
|
21546
|
+
function formatCountSummary(counts) {
|
|
21547
|
+
return Object.entries(counts).sort(([left], [right]) => left.localeCompare(right)).map(([key, count]) => `${key} ${count}`).join(", ");
|
|
21548
|
+
}
|
|
21398
21549
|
function printLoweringOutcome(outcome) {
|
|
21399
21550
|
const target = outcome.target ?? "workspace";
|
|
21400
21551
|
const policy = outcome.policy === undefined ? "" : ` policy: ${outcome.policy}`;
|
|
@@ -21409,8 +21560,8 @@ function printLoweringOutcome(outcome) {
|
|
|
21409
21560
|
}
|
|
21410
21561
|
function parseArgs(args) {
|
|
21411
21562
|
const command = args[0];
|
|
21412
|
-
if (command !== "adopt" && command !== "build" && command !== "change" && command !== "check" && command !== "ci" && command !== "create" && command !== "diff" && command !== "distribute" && command !== "doctor" && command !== "explain" && command !== "hooks" && command !== "import" && command !== "init" && command !== "lint" && command !== "list" && command !== "release" && command !== "restore" && command !== "test") {
|
|
21413
|
-
throw new Error(`skillset: expected command adopt, build, change, check, ci, create, diff, distribute, doctor, explain, hooks, import, init, lint, list, release, restore, or test
|
|
21563
|
+
if (command !== "adopt" && command !== "build" && command !== "change" && command !== "check" && command !== "ci" && command !== "create" && command !== "diff" && command !== "distribute" && command !== "doctor" && command !== "explain" && command !== "features" && command !== "hooks" && command !== "import" && command !== "init" && command !== "lint" && command !== "list" && command !== "release" && command !== "restore" && command !== "test") {
|
|
21564
|
+
throw new Error(`skillset: expected command adopt, build, change, check, ci, create, diff, distribute, doctor, explain, features, hooks, import, init, lint, list, release, restore, or test
|
|
21414
21565
|
` + USAGE);
|
|
21415
21566
|
}
|
|
21416
21567
|
let changeSubcommand;
|
|
@@ -21534,6 +21685,13 @@ function parseArgs(args) {
|
|
|
21534
21685
|
importPath = rawPath;
|
|
21535
21686
|
index += 1;
|
|
21536
21687
|
}
|
|
21688
|
+
if (command === "features") {
|
|
21689
|
+
const rawFeatureId = args[index];
|
|
21690
|
+
if (rawFeatureId !== undefined && !rawFeatureId.startsWith("--")) {
|
|
21691
|
+
importPath = rawFeatureId;
|
|
21692
|
+
index += 1;
|
|
21693
|
+
}
|
|
21694
|
+
}
|
|
21537
21695
|
if (command === "restore") {
|
|
21538
21696
|
const rawBackupId = args[index];
|
|
21539
21697
|
if (rawBackupId === undefined || rawBackupId.startsWith("--")) {
|
|
@@ -21989,9 +22147,9 @@ function validateAdoptFlags(command, adopt) {
|
|
|
21989
22147
|
function validateJsonFlags(command, jsonOutput) {
|
|
21990
22148
|
if (!jsonOutput)
|
|
21991
22149
|
return;
|
|
21992
|
-
if (command === "doctor" || command === "explain")
|
|
22150
|
+
if (command === "doctor" || command === "explain" || command === "features")
|
|
21993
22151
|
return;
|
|
21994
|
-
throw new Error("skillset: --json is only supported with doctor or
|
|
22152
|
+
throw new Error("skillset: --json is only supported with doctor, explain, or features");
|
|
21995
22153
|
}
|
|
21996
22154
|
function isImportKind(value) {
|
|
21997
22155
|
return value === "skill" || value === "skills" || value === "plugin" || value === "plugins";
|
package/package.json
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "skillset",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "Source-first compiler for Claude and Codex agent loadouts.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
7
7
|
"dist/*.js"
|
|
8
8
|
],
|
|
9
9
|
"publishConfig": {
|
|
10
|
-
"access": "public"
|
|
11
|
-
"tag": "beta"
|
|
10
|
+
"access": "public"
|
|
12
11
|
},
|
|
13
12
|
"repository": {
|
|
14
13
|
"type": "git",
|