skillops-cli 1.3.0 → 1.3.1
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 +1 -1
- package/dist/cli.js +505 -528
- package/dist/index.d.ts +137 -137
- package/dist/index.js +492 -494
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -6,15 +6,11 @@ import path10 from "path";
|
|
|
6
6
|
import { fileURLToPath, pathToFileURL } from "url";
|
|
7
7
|
import YAML6 from "yaml";
|
|
8
8
|
|
|
9
|
-
// src/auditor/parser.ts
|
|
10
|
-
import fs2 from "fs";
|
|
11
|
-
import path from "path";
|
|
12
|
-
|
|
13
9
|
// src/models.ts
|
|
14
10
|
import fs from "fs";
|
|
15
11
|
import YAML from "yaml";
|
|
16
12
|
import { z } from "zod";
|
|
17
|
-
var SKILLOPS_VERSION = "1.3.
|
|
13
|
+
var SKILLOPS_VERSION = "1.3.1";
|
|
18
14
|
var SKILL_NAME_REGEX = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
19
15
|
var SEMVER_REGEX = /^\d+\.\d+\.\d+$/;
|
|
20
16
|
var FRONTMATTER_REGEX = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/;
|
|
@@ -30,7 +26,9 @@ function estimateTokenCount(text) {
|
|
|
30
26
|
return 0;
|
|
31
27
|
}
|
|
32
28
|
const words = countWords(stripped);
|
|
33
|
-
const punctBonus = Math.floor(
|
|
29
|
+
const punctBonus = Math.floor(
|
|
30
|
+
(stripped.match(PUNCT_CODE_REGEX)?.length ?? 0) / 4
|
|
31
|
+
);
|
|
34
32
|
return Math.max(1, Math.ceil(words * 1.33) + punctBonus);
|
|
35
33
|
}
|
|
36
34
|
function splitFrontmatter(rawText, sourceLabel) {
|
|
@@ -44,7 +42,9 @@ function splitFrontmatter(rawText, sourceLabel) {
|
|
|
44
42
|
const body = match[2] ?? "";
|
|
45
43
|
const parsed = YAML.parse(yamlText);
|
|
46
44
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
47
|
-
throw new Error(
|
|
45
|
+
throw new Error(
|
|
46
|
+
`YAML frontmatter in '${sourceLabel}' must evaluate to a key-value mapping.`
|
|
47
|
+
);
|
|
48
48
|
}
|
|
49
49
|
return [parsed, body];
|
|
50
50
|
}
|
|
@@ -543,7 +543,9 @@ var SubagentManifestSchema = z.object({
|
|
|
543
543
|
});
|
|
544
544
|
}
|
|
545
545
|
}),
|
|
546
|
-
tools: z.array(z.string().min(1)).min(1, {
|
|
546
|
+
tools: z.array(z.string().min(1)).min(1, {
|
|
547
|
+
message: "Subagent must declare an explicit non-empty tool allowlist per INV-SKILL-04."
|
|
548
|
+
}).superRefine((tools, ctx) => {
|
|
547
549
|
for (const tool of tools) {
|
|
548
550
|
if (FORBIDDEN_WILDCARD_TOOLS.has(tool.trim().toLowerCase())) {
|
|
549
551
|
ctx.addIssue({
|
|
@@ -734,7 +736,14 @@ var SyncedArtifactSchema = z.object({
|
|
|
734
736
|
skill_name: z.string().min(1),
|
|
735
737
|
relative_path: z.string().min(1),
|
|
736
738
|
sha256: z.string().regex(/^[0-9a-f]{64}$/),
|
|
737
|
-
action: z.enum([
|
|
739
|
+
action: z.enum([
|
|
740
|
+
"created",
|
|
741
|
+
"updated",
|
|
742
|
+
"unchanged",
|
|
743
|
+
"removed",
|
|
744
|
+
"planned",
|
|
745
|
+
"conflict"
|
|
746
|
+
])
|
|
738
747
|
}).strict();
|
|
739
748
|
var SyncLockEntrySchema = z.object({
|
|
740
749
|
target: RuntimeTargetSchema,
|
|
@@ -820,6 +829,8 @@ function loadSkillOpsConfig(repoPath) {
|
|
|
820
829
|
}
|
|
821
830
|
|
|
822
831
|
// src/auditor/parser.ts
|
|
832
|
+
import fs2 from "fs";
|
|
833
|
+
import path from "path";
|
|
823
834
|
function walkForFilesNamed(rootDir, targetFilename) {
|
|
824
835
|
if (!fs2.existsSync(rootDir)) {
|
|
825
836
|
return [];
|
|
@@ -852,7 +863,10 @@ function parseSkillDirectory(skillDir, options = {}) {
|
|
|
852
863
|
const rawText = fs2.readFileSync(skillMdPath, "utf-8");
|
|
853
864
|
const lines = rawText.split(/\r?\n/);
|
|
854
865
|
const totalLines = rawText.endsWith("\n") ? lines.length - 1 : lines.length;
|
|
855
|
-
const [, markdownBody] = splitFrontmatter(
|
|
866
|
+
const [, markdownBody] = splitFrontmatter(
|
|
867
|
+
rawText,
|
|
868
|
+
skillMdPath.replace(/\\/g, "/")
|
|
869
|
+
);
|
|
856
870
|
const manifest = parseSkillMdFile(skillMdPath);
|
|
857
871
|
const declaredScripts = [];
|
|
858
872
|
const missingDeclaredScripts = [];
|
|
@@ -886,7 +900,9 @@ function parseSkillDirectory(skillDir, options = {}) {
|
|
|
886
900
|
const referencesDir = path.join(skillDir, "references");
|
|
887
901
|
const referenceFiles = [];
|
|
888
902
|
if (fs2.existsSync(referencesDir) && fs2.statSync(referencesDir).isDirectory()) {
|
|
889
|
-
for (const entry of fs2.readdirSync(referencesDir, {
|
|
903
|
+
for (const entry of fs2.readdirSync(referencesDir, {
|
|
904
|
+
withFileTypes: true
|
|
905
|
+
})) {
|
|
890
906
|
if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
891
907
|
referenceFiles.push(path.join(referencesDir, entry.name));
|
|
892
908
|
}
|
|
@@ -951,112 +967,6 @@ function parseSubagentFile(filePath) {
|
|
|
951
967
|
};
|
|
952
968
|
}
|
|
953
969
|
|
|
954
|
-
// src/auditor/token_budget.ts
|
|
955
|
-
function auditSkillTokenBudget(skillDir, options = {}) {
|
|
956
|
-
const requireLayout = options.requireLayout ?? false;
|
|
957
|
-
try {
|
|
958
|
-
const parsed = parseSkillDirectory(skillDir, { requireLayout });
|
|
959
|
-
const warnings = [];
|
|
960
|
-
const errors = [];
|
|
961
|
-
if (parsed.manifest.routing_signals.negative_triggers.length === 0 && !parsed.manifest.description.toLowerCase().includes("do not trigger")) {
|
|
962
|
-
warnings.push(
|
|
963
|
-
`Skill '${parsed.manifest.name}' has no explicit negative triggers ('Do not trigger for...' or routing_signals.negative_triggers).`
|
|
964
|
-
);
|
|
965
|
-
}
|
|
966
|
-
if (requireLayout && parsed.missingDeclaredScripts.length > 0) {
|
|
967
|
-
errors.push(
|
|
968
|
-
`Skill '${parsed.manifest.name}' is missing declared script(s): ${parsed.missingDeclaredScripts.join(", ")}`
|
|
969
|
-
);
|
|
970
|
-
}
|
|
971
|
-
return {
|
|
972
|
-
skillName: parsed.manifest.name,
|
|
973
|
-
skillDir: skillDir.replace(/\\/g, "/"),
|
|
974
|
-
l1Words: parsed.manifest.description_words,
|
|
975
|
-
l1Tokens: parsed.manifest.description_tokens,
|
|
976
|
-
l2Lines: parsed.manifest.body_lines,
|
|
977
|
-
l2Tokens: parsed.manifest.body_tokens,
|
|
978
|
-
totalLines: parsed.totalLines,
|
|
979
|
-
scriptsCount: parsed.declaredScripts.length,
|
|
980
|
-
passed: errors.length === 0,
|
|
981
|
-
errors,
|
|
982
|
-
warnings
|
|
983
|
-
};
|
|
984
|
-
} catch (err) {
|
|
985
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
986
|
-
return {
|
|
987
|
-
skillName: skillDir.split(/[\\/]/).pop() ?? "unknown",
|
|
988
|
-
skillDir: skillDir.replace(/\\/g, "/"),
|
|
989
|
-
l1Words: 0,
|
|
990
|
-
l1Tokens: 0,
|
|
991
|
-
l2Lines: 0,
|
|
992
|
-
l2Tokens: 0,
|
|
993
|
-
totalLines: 0,
|
|
994
|
-
scriptsCount: 0,
|
|
995
|
-
passed: false,
|
|
996
|
-
errors: [message],
|
|
997
|
-
warnings: []
|
|
998
|
-
};
|
|
999
|
-
}
|
|
1000
|
-
}
|
|
1001
|
-
function auditSubagentTokenBudget(filePath) {
|
|
1002
|
-
try {
|
|
1003
|
-
const parsed = parseSubagentFile(filePath);
|
|
1004
|
-
return {
|
|
1005
|
-
subagentName: parsed.manifest.name,
|
|
1006
|
-
filePath: filePath.replace(/\\/g, "/"),
|
|
1007
|
-
descriptionTokens: parsed.manifest.description_tokens,
|
|
1008
|
-
systemPromptLines: parsed.manifest.system_prompt_lines,
|
|
1009
|
-
systemPromptTokens: parsed.manifest.system_prompt_tokens,
|
|
1010
|
-
maxOutputTokens: parsed.manifest.max_output_tokens,
|
|
1011
|
-
tools: parsed.manifest.tools,
|
|
1012
|
-
passed: true,
|
|
1013
|
-
errors: []
|
|
1014
|
-
};
|
|
1015
|
-
} catch (err) {
|
|
1016
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
1017
|
-
return {
|
|
1018
|
-
subagentName: filePath.split(/[\\/]/).pop() ?? "unknown",
|
|
1019
|
-
filePath: filePath.replace(/\\/g, "/"),
|
|
1020
|
-
descriptionTokens: 0,
|
|
1021
|
-
systemPromptLines: 0,
|
|
1022
|
-
systemPromptTokens: 0,
|
|
1023
|
-
maxOutputTokens: 0,
|
|
1024
|
-
tools: [],
|
|
1025
|
-
passed: false,
|
|
1026
|
-
errors: [message]
|
|
1027
|
-
};
|
|
1028
|
-
}
|
|
1029
|
-
}
|
|
1030
|
-
function auditCatalogTokenBudgets(catalogDir, options = {}) {
|
|
1031
|
-
const skillDirs = discoverSkillDirectories(catalogDir);
|
|
1032
|
-
const subagentFiles = discoverSubagentFiles(catalogDir);
|
|
1033
|
-
const skills = skillDirs.map((dir) => auditSkillTokenBudget(dir, options));
|
|
1034
|
-
const subagents = subagentFiles.map((file) => auditSubagentTokenBudget(file));
|
|
1035
|
-
const errors = [];
|
|
1036
|
-
const warnings = [];
|
|
1037
|
-
let totalL1Tokens = 0;
|
|
1038
|
-
let totalSubagentPromptTokens = 0;
|
|
1039
|
-
for (const s of skills) {
|
|
1040
|
-
totalL1Tokens += s.l1Tokens;
|
|
1041
|
-
errors.push(...s.errors);
|
|
1042
|
-
warnings.push(...s.warnings);
|
|
1043
|
-
}
|
|
1044
|
-
for (const sa of subagents) {
|
|
1045
|
-
totalSubagentPromptTokens += sa.systemPromptTokens;
|
|
1046
|
-
errors.push(...sa.errors);
|
|
1047
|
-
}
|
|
1048
|
-
return {
|
|
1049
|
-
catalogPath: catalogDir.replace(/\\/g, "/"),
|
|
1050
|
-
skills,
|
|
1051
|
-
subagents,
|
|
1052
|
-
totalL1Tokens,
|
|
1053
|
-
totalSubagentPromptTokens,
|
|
1054
|
-
errors,
|
|
1055
|
-
warnings,
|
|
1056
|
-
passed: errors.length === 0
|
|
1057
|
-
};
|
|
1058
|
-
}
|
|
1059
|
-
|
|
1060
970
|
// src/auditor/collision.ts
|
|
1061
971
|
var ROUTING_STOPWORDS = /* @__PURE__ */ new Set([
|
|
1062
972
|
"a",
|
|
@@ -1385,6 +1295,12 @@ function auditCatalog(catalogDir, options = {}) {
|
|
|
1385
1295
|
});
|
|
1386
1296
|
}
|
|
1387
1297
|
|
|
1298
|
+
// src/auditor/doctor.ts
|
|
1299
|
+
import { spawnSync } from "child_process";
|
|
1300
|
+
import crypto from "crypto";
|
|
1301
|
+
import fs4 from "fs";
|
|
1302
|
+
import path3 from "path";
|
|
1303
|
+
|
|
1388
1304
|
// src/auditor/token_economy.ts
|
|
1389
1305
|
import fs3 from "fs";
|
|
1390
1306
|
import path2 from "path";
|
|
@@ -1456,42 +1372,10 @@ function padVisible(text, width, align = "left") {
|
|
|
1456
1372
|
}
|
|
1457
1373
|
return `${text}${" ".repeat(diff)}`;
|
|
1458
1374
|
}
|
|
1459
|
-
function
|
|
1460
|
-
const paddingX = options?.paddingX ?? 2;
|
|
1461
|
-
const minWidth = options?.minWidth ?? 64;
|
|
1462
|
-
const colorEnabled = options?.colorEnabled;
|
|
1463
|
-
const borderFn = options?.borderColor ?? style.cyan;
|
|
1464
|
-
const titleText = options?.title ? ` ${options.title.trim()} ` : "";
|
|
1465
|
-
const titleVisibleLen = visibleLength(titleText);
|
|
1466
|
-
const maxLineLen = lines.reduce(
|
|
1467
|
-
(max, line) => Math.max(max, visibleLength(line)),
|
|
1468
|
-
0
|
|
1469
|
-
);
|
|
1470
|
-
const innerWidth = Math.max(
|
|
1471
|
-
minWidth,
|
|
1472
|
-
maxLineLen + paddingX * 2,
|
|
1473
|
-
titleVisibleLen + 4
|
|
1474
|
-
);
|
|
1475
|
-
const contentWidth = innerWidth - paddingX * 2;
|
|
1476
|
-
const padStr = " ".repeat(paddingX);
|
|
1477
|
-
const topBorder = titleVisibleLen > 0 ? `${borderFn("\u256D\u2500", colorEnabled)}${style.bold(titleText, colorEnabled)}${borderFn(`${"\u2500".repeat(Math.max(1, innerWidth - titleVisibleLen - 1))}\u256E`, colorEnabled)}` : borderFn(`\u256D${"\u2500".repeat(innerWidth)}\u256E`, colorEnabled);
|
|
1478
|
-
const bodyLines = lines.map((line) => {
|
|
1479
|
-
const padded = padVisible(line, contentWidth, "left");
|
|
1480
|
-
return `${borderFn("\u2502", colorEnabled)}${padStr}${padded}${padStr}${borderFn("\u2502", colorEnabled)}`;
|
|
1481
|
-
});
|
|
1482
|
-
const bottomBorder = borderFn(`\u2570${"\u2500".repeat(innerWidth)}\u256F`, colorEnabled);
|
|
1483
|
-
return [topBorder, ...bodyLines, bottomBorder].join("\n");
|
|
1484
|
-
}
|
|
1485
|
-
function renderHeaderBanner(subtitle = "Framework & Library for High-End AI Coding Skills & Subagents", options) {
|
|
1375
|
+
function renderHeaderBanner(subtitle = "Framework & Library for AI Skills & Subagents", options) {
|
|
1486
1376
|
const ver = options?.version ?? SKILLOPS_VERSION;
|
|
1487
1377
|
const c = options?.colorEnabled;
|
|
1488
|
-
|
|
1489
|
-
return renderBox([headline], {
|
|
1490
|
-
borderColor: style.cyan,
|
|
1491
|
-
paddingX: 2,
|
|
1492
|
-
minWidth: 72,
|
|
1493
|
-
colorEnabled: c
|
|
1494
|
-
});
|
|
1378
|
+
return `${style.bold(style.cyan(`\u25C6 SkillOps v${ver}`, c), c)} ${style.dim("\u2014", c)} ${subtitle}`;
|
|
1495
1379
|
}
|
|
1496
1380
|
function renderTable(headers, rows, options) {
|
|
1497
1381
|
const indent = " ".repeat(options?.indent ?? 2);
|
|
@@ -1524,7 +1408,7 @@ function renderTable(headers, rows, options) {
|
|
|
1524
1408
|
].join("\n");
|
|
1525
1409
|
}
|
|
1526
1410
|
function renderTokenBar(current, max, options) {
|
|
1527
|
-
const width = options?.width ??
|
|
1411
|
+
const width = options?.width ?? 10;
|
|
1528
1412
|
const unit = options?.unit ?? "tokens";
|
|
1529
1413
|
const c = options?.colorEnabled;
|
|
1530
1414
|
const safeMax = max > 0 ? max : 1;
|
|
@@ -1542,9 +1426,8 @@ function renderTokenBar(current, max, options) {
|
|
|
1542
1426
|
var renderProgressBar = renderTokenBar;
|
|
1543
1427
|
function renderSectionHeader(title, colorEnabled) {
|
|
1544
1428
|
const c = colorEnabled;
|
|
1545
|
-
return
|
|
1546
|
-
|
|
1547
|
-
${style.dim("\u2500".repeat(Math.max(24, visibleLength(title))), c)}`;
|
|
1429
|
+
return `${style.dim("\u2502", c)}
|
|
1430
|
+
${style.dim("\u251C\u2500", c)} ${style.bold(style.cyan(title, c), c)}`;
|
|
1548
1431
|
}
|
|
1549
1432
|
function formatBadge(type, customLabel, colorEnabled) {
|
|
1550
1433
|
switch (type) {
|
|
@@ -1583,73 +1466,72 @@ function formatBadge(type, customLabel, colorEnabled) {
|
|
|
1583
1466
|
function renderStep(step, total, title, detail, status = "done", colorEnabled) {
|
|
1584
1467
|
const icon = status === "done" ? style.green("\u2714", colorEnabled) : status === "warn" ? style.yellow("\u26A0", colorEnabled) : style.dim("\u25CB", colorEnabled);
|
|
1585
1468
|
const stepBadge = style.dim(`[${step}/${total}]`, colorEnabled);
|
|
1586
|
-
const titleStyled = style.bold(padVisible(title,
|
|
1587
|
-
const detailStyled = detail ? ` ${style.dim("\
|
|
1588
|
-
return
|
|
1469
|
+
const titleStyled = style.bold(padVisible(title, 20, "left"), colorEnabled);
|
|
1470
|
+
const detailStyled = detail ? ` ${style.dim("\xB7", colorEnabled)} ${detail}` : "";
|
|
1471
|
+
return `${style.dim("\u2502", colorEnabled)} ${icon} ${stepBadge} ${titleStyled}${detailStyled}`;
|
|
1589
1472
|
}
|
|
1590
1473
|
function renderNextSteps(hints, colorEnabled) {
|
|
1591
1474
|
if (hints.length === 0) {
|
|
1592
1475
|
return "";
|
|
1593
1476
|
}
|
|
1594
1477
|
const c = colorEnabled;
|
|
1595
|
-
const maxCmdLen =
|
|
1596
|
-
|
|
1597
|
-
0
|
|
1478
|
+
const maxCmdLen = Math.min(
|
|
1479
|
+
44,
|
|
1480
|
+
hints.reduce((m, h) => Math.max(m, visibleLength(h.command)), 0)
|
|
1598
1481
|
);
|
|
1599
1482
|
const lines = [
|
|
1600
|
-
"",
|
|
1601
|
-
|
|
1602
|
-
...hints.map(
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1483
|
+
style.dim("\u2502", c),
|
|
1484
|
+
`${style.dim("\u2570\u2500", c)} ${style.bold(style.cyan("Next Steps:", c), c)}`,
|
|
1485
|
+
...hints.map((h) => {
|
|
1486
|
+
const cmdPadded = padVisible(h.command, maxCmdLen, "left");
|
|
1487
|
+
const prefixCols = 5 + visibleLength(cmdPadded) + 3;
|
|
1488
|
+
const maxDescCols = Math.max(10, 76 - prefixCols);
|
|
1489
|
+
const desc = h.description.length > maxDescCols ? `${h.description.slice(0, maxDescCols - 1)}\u2026` : h.description;
|
|
1490
|
+
return ` ${style.dim("$", c)} ${style.green(cmdPadded, c)} ${style.dim(`\u2014 ${desc}`, c)}`;
|
|
1491
|
+
})
|
|
1606
1492
|
];
|
|
1607
|
-
return lines.join("\n")
|
|
1493
|
+
return `${lines.join("\n")}
|
|
1494
|
+
`;
|
|
1608
1495
|
}
|
|
1609
1496
|
function renderAiUsageGuide(targets, skills, subagents, colorEnabled) {
|
|
1610
1497
|
const c = colorEnabled;
|
|
1611
1498
|
const sampleSkill = skills[0] ?? "systematic-debugging";
|
|
1612
1499
|
const sampleAgent = subagents[0] ?? "context-scout";
|
|
1500
|
+
const bar = style.dim("\u2502", c);
|
|
1613
1501
|
const lines = [
|
|
1614
|
-
|
|
1615
|
-
""
|
|
1502
|
+
bar,
|
|
1503
|
+
`${style.dim("\u251C\u2500", c)} ${style.bold(style.cyan("Using Your Skills & Subagents", c), c)}`
|
|
1616
1504
|
];
|
|
1617
1505
|
const targetSet = new Set(targets);
|
|
1618
1506
|
if (targetSet.has("claude") || targetSet.size === 0) {
|
|
1619
1507
|
lines.push(
|
|
1620
|
-
|
|
1508
|
+
`${bar} \u2022 ${style.bold("Claude Code:", c)} Auto-routed (${sampleSkill}) or @${sampleAgent}`
|
|
1621
1509
|
);
|
|
1622
1510
|
}
|
|
1623
1511
|
if (targetSet.has("cursor")) {
|
|
1624
1512
|
lines.push(
|
|
1625
|
-
|
|
1513
|
+
`${bar} \u2022 ${style.bold("Cursor IDE:", c)} Type ${style.cyan(`@${sampleSkill}`, c)} in Chat (.cursor/rules/)`
|
|
1626
1514
|
);
|
|
1627
1515
|
}
|
|
1628
1516
|
if (targetSet.has("antigravity")) {
|
|
1629
1517
|
lines.push(
|
|
1630
|
-
|
|
1518
|
+
`${bar} \u2022 ${style.bold("Antigravity:", c)} Auto-activated (.agent/skills/${sampleSkill})`
|
|
1631
1519
|
);
|
|
1632
1520
|
}
|
|
1633
1521
|
if (targetSet.has("copilot")) {
|
|
1634
1522
|
lines.push(
|
|
1635
|
-
|
|
1523
|
+
`${bar} \u2022 ${style.bold("Copilot:", c)} Use ${style.cyan(`/${sampleSkill}`, c)} in Chat (.github/instructions/)`
|
|
1636
1524
|
);
|
|
1637
1525
|
}
|
|
1638
1526
|
if (targetSet.has("windsurf") || targetSet.has("cline") || targetSet.has("roocode") || targetSet.has("kilocode")) {
|
|
1639
1527
|
lines.push(
|
|
1640
|
-
|
|
1528
|
+
`${bar} \u2022 ${style.bold("Windsurf/Cline/Roo/Kilo:", c)} Workspace rules load automatically`
|
|
1641
1529
|
);
|
|
1642
1530
|
}
|
|
1643
1531
|
lines.push(
|
|
1644
|
-
|
|
1532
|
+
`${bar} \u2022 ${style.bold("Inspect:", c)} ${style.green(`npx skillops-cli info ${sampleSkill}`, c)}`
|
|
1645
1533
|
);
|
|
1646
|
-
return
|
|
1647
|
-
title: "\u{1F680} Using Your Skills & Subagents",
|
|
1648
|
-
borderColor: style.green,
|
|
1649
|
-
paddingX: 2,
|
|
1650
|
-
minWidth: 72,
|
|
1651
|
-
colorEnabled: c
|
|
1652
|
-
});
|
|
1534
|
+
return lines.join("\n");
|
|
1653
1535
|
}
|
|
1654
1536
|
function levenshteinDistance(a, b) {
|
|
1655
1537
|
const s1 = a.toLowerCase();
|
|
@@ -2087,7 +1969,7 @@ function formatTokenEconomyReport(report, format = "table") {
|
|
|
2087
1969
|
const startupBar = renderProgressBar(
|
|
2088
1970
|
report.startup_token_tax,
|
|
2089
1971
|
report.startup_tax_budget,
|
|
2090
|
-
{ width:
|
|
1972
|
+
{ width: 10, unit: "tokens" }
|
|
2091
1973
|
);
|
|
2092
1974
|
const lines = [
|
|
2093
1975
|
"=== SkillOps Token Economy & Startup Context Tax Analyzer ===",
|
|
@@ -2112,11 +1994,11 @@ function formatTokenEconomyReport(report, format = "table") {
|
|
|
2112
1994
|
renderNextSteps([
|
|
2113
1995
|
{
|
|
2114
1996
|
command: "npx skillops-cli quickstart",
|
|
2115
|
-
description: "Sync Progressive Disclosure Skills &
|
|
1997
|
+
description: "Sync Progressive Disclosure Skills & Subagents"
|
|
2116
1998
|
},
|
|
2117
1999
|
{
|
|
2118
2000
|
command: "npx skillops-cli doctor",
|
|
2119
|
-
description: "Inspect
|
|
2001
|
+
description: "Inspect lockfile & startup tax diagnostics"
|
|
2120
2002
|
}
|
|
2121
2003
|
]).trimEnd()
|
|
2122
2004
|
);
|
|
@@ -2125,10 +2007,6 @@ function formatTokenEconomyReport(report, format = "table") {
|
|
|
2125
2007
|
}
|
|
2126
2008
|
|
|
2127
2009
|
// src/auditor/doctor.ts
|
|
2128
|
-
import { spawnSync } from "child_process";
|
|
2129
|
-
import crypto from "crypto";
|
|
2130
|
-
import fs4 from "fs";
|
|
2131
|
-
import path3 from "path";
|
|
2132
2010
|
function computeFileSha256(content) {
|
|
2133
2011
|
return crypto.createHash("sha256").update(content, "utf-8").digest("hex");
|
|
2134
2012
|
}
|
|
@@ -2360,10 +2238,12 @@ function inspectHarnesses(repoPath) {
|
|
|
2360
2238
|
const repoLabel = path3.basename(resolvedRepo) || ".";
|
|
2361
2239
|
const detectedHarnesses = detectInstalledHarnesses(resolvedRepo);
|
|
2362
2240
|
const detectedSet = new Set(detectedHarnesses);
|
|
2363
|
-
const harnesses = ALL_RUNTIME_TARGETS.map(
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2241
|
+
const harnesses = ALL_RUNTIME_TARGETS.map(
|
|
2242
|
+
(target) => ({
|
|
2243
|
+
...RUNTIME_HARNESS_SPECS[target],
|
|
2244
|
+
detected: detectedSet.has(target)
|
|
2245
|
+
})
|
|
2246
|
+
);
|
|
2367
2247
|
return {
|
|
2368
2248
|
repo_path: repoLabel,
|
|
2369
2249
|
total_supported: harnesses.length,
|
|
@@ -2420,9 +2300,13 @@ function formatDoctorReport(report, format = "table") {
|
|
|
2420
2300
|
}
|
|
2421
2301
|
for (const check of report.checks) {
|
|
2422
2302
|
if (check.status === "fail") {
|
|
2423
|
-
lines2.push(
|
|
2303
|
+
lines2.push(
|
|
2304
|
+
`::error title=SkillOps Doctor (${check.title})::${check.summary}`
|
|
2305
|
+
);
|
|
2424
2306
|
} else if (check.status === "warn") {
|
|
2425
|
-
lines2.push(
|
|
2307
|
+
lines2.push(
|
|
2308
|
+
`::warning title=SkillOps Doctor (${check.title})::${check.summary}`
|
|
2309
|
+
);
|
|
2426
2310
|
}
|
|
2427
2311
|
}
|
|
2428
2312
|
lines2.push(
|
|
@@ -2492,7 +2376,9 @@ function formatDoctorReport(report, format = "table") {
|
|
|
2492
2376
|
lines.push("-".repeat(64), "Tracked Lockfile Artifacts:");
|
|
2493
2377
|
for (const art of report.artifacts) {
|
|
2494
2378
|
const badge = art.status === "healthy" ? "[HEALTHY]" : art.status === "drifted" ? "[DRIFTED]" : "[MISSING]";
|
|
2495
|
-
lines.push(
|
|
2379
|
+
lines.push(
|
|
2380
|
+
` ${badge} ${art.relative_path} (${art.target} :: ${art.item_name})`
|
|
2381
|
+
);
|
|
2496
2382
|
}
|
|
2497
2383
|
}
|
|
2498
2384
|
if (report.remediation.length > 0) {
|
|
@@ -2504,6 +2390,112 @@ function formatDoctorReport(report, format = "table") {
|
|
|
2504
2390
|
return lines.join("\n");
|
|
2505
2391
|
}
|
|
2506
2392
|
|
|
2393
|
+
// src/auditor/token_budget.ts
|
|
2394
|
+
function auditSkillTokenBudget(skillDir, options = {}) {
|
|
2395
|
+
const requireLayout = options.requireLayout ?? false;
|
|
2396
|
+
try {
|
|
2397
|
+
const parsed = parseSkillDirectory(skillDir, { requireLayout });
|
|
2398
|
+
const warnings = [];
|
|
2399
|
+
const errors = [];
|
|
2400
|
+
if (parsed.manifest.routing_signals.negative_triggers.length === 0 && !parsed.manifest.description.toLowerCase().includes("do not trigger")) {
|
|
2401
|
+
warnings.push(
|
|
2402
|
+
`Skill '${parsed.manifest.name}' has no explicit negative triggers ('Do not trigger for...' or routing_signals.negative_triggers).`
|
|
2403
|
+
);
|
|
2404
|
+
}
|
|
2405
|
+
if (requireLayout && parsed.missingDeclaredScripts.length > 0) {
|
|
2406
|
+
errors.push(
|
|
2407
|
+
`Skill '${parsed.manifest.name}' is missing declared script(s): ${parsed.missingDeclaredScripts.join(", ")}`
|
|
2408
|
+
);
|
|
2409
|
+
}
|
|
2410
|
+
return {
|
|
2411
|
+
skillName: parsed.manifest.name,
|
|
2412
|
+
skillDir: skillDir.replace(/\\/g, "/"),
|
|
2413
|
+
l1Words: parsed.manifest.description_words,
|
|
2414
|
+
l1Tokens: parsed.manifest.description_tokens,
|
|
2415
|
+
l2Lines: parsed.manifest.body_lines,
|
|
2416
|
+
l2Tokens: parsed.manifest.body_tokens,
|
|
2417
|
+
totalLines: parsed.totalLines,
|
|
2418
|
+
scriptsCount: parsed.declaredScripts.length,
|
|
2419
|
+
passed: errors.length === 0,
|
|
2420
|
+
errors,
|
|
2421
|
+
warnings
|
|
2422
|
+
};
|
|
2423
|
+
} catch (err) {
|
|
2424
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
2425
|
+
return {
|
|
2426
|
+
skillName: skillDir.split(/[\\/]/).pop() ?? "unknown",
|
|
2427
|
+
skillDir: skillDir.replace(/\\/g, "/"),
|
|
2428
|
+
l1Words: 0,
|
|
2429
|
+
l1Tokens: 0,
|
|
2430
|
+
l2Lines: 0,
|
|
2431
|
+
l2Tokens: 0,
|
|
2432
|
+
totalLines: 0,
|
|
2433
|
+
scriptsCount: 0,
|
|
2434
|
+
passed: false,
|
|
2435
|
+
errors: [message],
|
|
2436
|
+
warnings: []
|
|
2437
|
+
};
|
|
2438
|
+
}
|
|
2439
|
+
}
|
|
2440
|
+
function auditSubagentTokenBudget(filePath) {
|
|
2441
|
+
try {
|
|
2442
|
+
const parsed = parseSubagentFile(filePath);
|
|
2443
|
+
return {
|
|
2444
|
+
subagentName: parsed.manifest.name,
|
|
2445
|
+
filePath: filePath.replace(/\\/g, "/"),
|
|
2446
|
+
descriptionTokens: parsed.manifest.description_tokens,
|
|
2447
|
+
systemPromptLines: parsed.manifest.system_prompt_lines,
|
|
2448
|
+
systemPromptTokens: parsed.manifest.system_prompt_tokens,
|
|
2449
|
+
maxOutputTokens: parsed.manifest.max_output_tokens,
|
|
2450
|
+
tools: parsed.manifest.tools,
|
|
2451
|
+
passed: true,
|
|
2452
|
+
errors: []
|
|
2453
|
+
};
|
|
2454
|
+
} catch (err) {
|
|
2455
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
2456
|
+
return {
|
|
2457
|
+
subagentName: filePath.split(/[\\/]/).pop() ?? "unknown",
|
|
2458
|
+
filePath: filePath.replace(/\\/g, "/"),
|
|
2459
|
+
descriptionTokens: 0,
|
|
2460
|
+
systemPromptLines: 0,
|
|
2461
|
+
systemPromptTokens: 0,
|
|
2462
|
+
maxOutputTokens: 0,
|
|
2463
|
+
tools: [],
|
|
2464
|
+
passed: false,
|
|
2465
|
+
errors: [message]
|
|
2466
|
+
};
|
|
2467
|
+
}
|
|
2468
|
+
}
|
|
2469
|
+
function auditCatalogTokenBudgets(catalogDir, options = {}) {
|
|
2470
|
+
const skillDirs = discoverSkillDirectories(catalogDir);
|
|
2471
|
+
const subagentFiles = discoverSubagentFiles(catalogDir);
|
|
2472
|
+
const skills = skillDirs.map((dir) => auditSkillTokenBudget(dir, options));
|
|
2473
|
+
const subagents = subagentFiles.map((file) => auditSubagentTokenBudget(file));
|
|
2474
|
+
const errors = [];
|
|
2475
|
+
const warnings = [];
|
|
2476
|
+
let totalL1Tokens = 0;
|
|
2477
|
+
let totalSubagentPromptTokens = 0;
|
|
2478
|
+
for (const s of skills) {
|
|
2479
|
+
totalL1Tokens += s.l1Tokens;
|
|
2480
|
+
errors.push(...s.errors);
|
|
2481
|
+
warnings.push(...s.warnings);
|
|
2482
|
+
}
|
|
2483
|
+
for (const sa of subagents) {
|
|
2484
|
+
totalSubagentPromptTokens += sa.systemPromptTokens;
|
|
2485
|
+
errors.push(...sa.errors);
|
|
2486
|
+
}
|
|
2487
|
+
return {
|
|
2488
|
+
catalogPath: catalogDir.replace(/\\/g, "/"),
|
|
2489
|
+
skills,
|
|
2490
|
+
subagents,
|
|
2491
|
+
totalL1Tokens,
|
|
2492
|
+
totalSubagentPromptTokens,
|
|
2493
|
+
errors,
|
|
2494
|
+
warnings,
|
|
2495
|
+
passed: errors.length === 0
|
|
2496
|
+
};
|
|
2497
|
+
}
|
|
2498
|
+
|
|
2507
2499
|
// src/eval/index.ts
|
|
2508
2500
|
import fs5 from "fs";
|
|
2509
2501
|
import path4 from "path";
|
|
@@ -2563,10 +2555,15 @@ function evaluateSkillDirectory(skillDir) {
|
|
|
2563
2555
|
const evalsPath = path4.join(skillDir, "evals", "evals.json");
|
|
2564
2556
|
const rawSuite = JSON.parse(fs5.readFileSync(evalsPath, "utf-8"));
|
|
2565
2557
|
const suite = SkillEvalSuiteSchema.parse(rawSuite);
|
|
2566
|
-
const assertionsCount = suite.evals.reduce(
|
|
2558
|
+
const assertionsCount = suite.evals.reduce(
|
|
2559
|
+
(acc, c) => acc + c.assertions.length,
|
|
2560
|
+
0
|
|
2561
|
+
);
|
|
2567
2562
|
const benchmarkPath = path4.join(skillDir, "evals", "benchmark.json");
|
|
2568
2563
|
if (fs5.existsSync(benchmarkPath) && fs5.statSync(benchmarkPath).isFile()) {
|
|
2569
|
-
const rawBench = JSON.parse(
|
|
2564
|
+
const rawBench = JSON.parse(
|
|
2565
|
+
fs5.readFileSync(benchmarkPath, "utf-8")
|
|
2566
|
+
);
|
|
2570
2567
|
const bench = SkillBenchmarkSchema.parse({
|
|
2571
2568
|
...rawBench,
|
|
2572
2569
|
eval_cases_count: suite.evals.length,
|
|
@@ -2622,18 +2619,25 @@ function evaluateCatalog(catalogDir, options = {}) {
|
|
|
2622
2619
|
}
|
|
2623
2620
|
const count = benchmarks.length;
|
|
2624
2621
|
const meanWith = count > 0 ? Number(
|
|
2625
|
-
(benchmarks.reduce(
|
|
2622
|
+
(benchmarks.reduce(
|
|
2623
|
+
(acc, b) => acc + b.with_skill.pass_rate_mean,
|
|
2624
|
+
0
|
|
2625
|
+
) / count).toFixed(4)
|
|
2626
2626
|
) : 0;
|
|
2627
2627
|
const meanWithout = count > 0 ? Number(
|
|
2628
|
-
(benchmarks.reduce(
|
|
2629
|
-
|
|
2630
|
-
|
|
2628
|
+
(benchmarks.reduce(
|
|
2629
|
+
(acc, b) => acc + b.without_skill.pass_rate_mean,
|
|
2630
|
+
0
|
|
2631
|
+
) / count).toFixed(4)
|
|
2631
2632
|
) : 0;
|
|
2632
2633
|
const meanGain = count > 0 ? Number(
|
|
2633
2634
|
(benchmarks.reduce((acc, b) => acc + b.delta.pass_rate_gain, 0) / count).toFixed(4)
|
|
2634
2635
|
) : 0;
|
|
2635
2636
|
const meanTokRed = count > 0 ? Number(
|
|
2636
|
-
(benchmarks.reduce(
|
|
2637
|
+
(benchmarks.reduce(
|
|
2638
|
+
(acc, b) => acc + b.delta.token_reduction_pct,
|
|
2639
|
+
0
|
|
2640
|
+
) / count).toFixed(2)
|
|
2637
2641
|
) : 0;
|
|
2638
2642
|
return CatalogEvalSummarySchema.parse({
|
|
2639
2643
|
catalog_path: resolvedCatalog.replace(/\\/g, "/"),
|
|
@@ -2739,6 +2743,9 @@ import path7 from "path";
|
|
|
2739
2743
|
import readline from "readline";
|
|
2740
2744
|
import YAML3 from "yaml";
|
|
2741
2745
|
|
|
2746
|
+
// src/router/bundle_compiler.ts
|
|
2747
|
+
import path6 from "path";
|
|
2748
|
+
|
|
2742
2749
|
// src/router/fingerprinter.ts
|
|
2743
2750
|
import fs6 from "fs";
|
|
2744
2751
|
import path5 from "path";
|
|
@@ -2838,13 +2845,17 @@ var RepoFingerprinter = class {
|
|
|
2838
2845
|
python312Plus = true;
|
|
2839
2846
|
signals.add("python3.12");
|
|
2840
2847
|
}
|
|
2841
|
-
const quotedSpecs = content.match(
|
|
2848
|
+
const quotedSpecs = content.match(
|
|
2849
|
+
/["']([a-zA-Z0-9._-]+(?:\[[a-zA-Z0-9,_-]+\])?\s*(?:[><=~!][^"']+)?)["']/g
|
|
2850
|
+
) ?? [];
|
|
2842
2851
|
for (const spec of quotedSpecs) {
|
|
2843
2852
|
recordDep(spec);
|
|
2844
2853
|
}
|
|
2845
2854
|
}
|
|
2846
2855
|
if (fs6.existsSync(this.repoPath)) {
|
|
2847
|
-
for (const entry of fs6.readdirSync(this.repoPath, {
|
|
2856
|
+
for (const entry of fs6.readdirSync(this.repoPath, {
|
|
2857
|
+
withFileTypes: true
|
|
2858
|
+
})) {
|
|
2848
2859
|
if (entry.isFile() && /^requirements.*\.txt$/i.test(entry.name)) {
|
|
2849
2860
|
detectedFiles.add(entry.name);
|
|
2850
2861
|
languages.add("python");
|
|
@@ -2864,8 +2875,14 @@ var RepoFingerprinter = class {
|
|
|
2864
2875
|
signals.add("nodejs");
|
|
2865
2876
|
signals.add("package.json");
|
|
2866
2877
|
try {
|
|
2867
|
-
const pkgJson = JSON.parse(
|
|
2868
|
-
|
|
2878
|
+
const pkgJson = JSON.parse(
|
|
2879
|
+
fs6.readFileSync(pkgJsonPath, "utf-8")
|
|
2880
|
+
);
|
|
2881
|
+
const depSections = [
|
|
2882
|
+
"dependencies",
|
|
2883
|
+
"devDependencies",
|
|
2884
|
+
"peerDependencies"
|
|
2885
|
+
];
|
|
2869
2886
|
for (const section of depSections) {
|
|
2870
2887
|
const obj = pkgJson[section];
|
|
2871
2888
|
if (obj && typeof obj === "object") {
|
|
@@ -2969,7 +2986,6 @@ function fingerprintRepository(repoPath) {
|
|
|
2969
2986
|
}
|
|
2970
2987
|
|
|
2971
2988
|
// src/router/bundle_compiler.ts
|
|
2972
|
-
import path6 from "path";
|
|
2973
2989
|
function scoreSkillAgainstProfile(parsedSkill, profile, taskPrompt = "") {
|
|
2974
2990
|
const manifest = parsedSkill.manifest;
|
|
2975
2991
|
const repoSignalSet = new Set(
|
|
@@ -3190,7 +3206,7 @@ function formatRoutedBundle(bundle, format = "table", colorEnabled) {
|
|
|
3190
3206
|
bundle.total_l1_tokens,
|
|
3191
3207
|
bundle.max_l1_tokens,
|
|
3192
3208
|
{
|
|
3193
|
-
width:
|
|
3209
|
+
width: 10,
|
|
3194
3210
|
unit: "tokens",
|
|
3195
3211
|
colorEnabled
|
|
3196
3212
|
}
|
|
@@ -3199,11 +3215,11 @@ function formatRoutedBundle(bundle, format = "table", colorEnabled) {
|
|
|
3199
3215
|
[
|
|
3200
3216
|
{
|
|
3201
3217
|
command: "npx skillops-cli quickstart",
|
|
3202
|
-
description: "Install
|
|
3218
|
+
description: "Install recommended bundle & wire MCP"
|
|
3203
3219
|
},
|
|
3204
3220
|
{
|
|
3205
3221
|
command: `npx skillops-cli info ${topSkill}`,
|
|
3206
|
-
description: `Inspect ${topSkill} triggers
|
|
3222
|
+
description: `Inspect ${topSkill} triggers & L3 scripts`
|
|
3207
3223
|
}
|
|
3208
3224
|
],
|
|
3209
3225
|
colorEnabled
|
|
@@ -3230,7 +3246,10 @@ var MCP_TOOLS = [
|
|
|
3230
3246
|
inputSchema: {
|
|
3231
3247
|
type: "object",
|
|
3232
3248
|
properties: {
|
|
3233
|
-
catalog_dir: {
|
|
3249
|
+
catalog_dir: {
|
|
3250
|
+
type: "string",
|
|
3251
|
+
description: "Optional path to catalog directory."
|
|
3252
|
+
}
|
|
3234
3253
|
},
|
|
3235
3254
|
additionalProperties: false
|
|
3236
3255
|
}
|
|
@@ -3241,8 +3260,14 @@ var MCP_TOOLS = [
|
|
|
3241
3260
|
inputSchema: {
|
|
3242
3261
|
type: "object",
|
|
3243
3262
|
properties: {
|
|
3244
|
-
repo_path: {
|
|
3245
|
-
|
|
3263
|
+
repo_path: {
|
|
3264
|
+
type: "string",
|
|
3265
|
+
description: "Target repository root path."
|
|
3266
|
+
},
|
|
3267
|
+
startup_tax_budget: {
|
|
3268
|
+
type: "number",
|
|
3269
|
+
description: "Max startup token budget."
|
|
3270
|
+
}
|
|
3246
3271
|
},
|
|
3247
3272
|
additionalProperties: false
|
|
3248
3273
|
}
|
|
@@ -3253,8 +3278,14 @@ var MCP_TOOLS = [
|
|
|
3253
3278
|
inputSchema: {
|
|
3254
3279
|
type: "object",
|
|
3255
3280
|
properties: {
|
|
3256
|
-
repo_path: {
|
|
3257
|
-
|
|
3281
|
+
repo_path: {
|
|
3282
|
+
type: "string",
|
|
3283
|
+
description: "Target repository root path."
|
|
3284
|
+
},
|
|
3285
|
+
task_prompt: {
|
|
3286
|
+
type: "string",
|
|
3287
|
+
description: "Optional developer task description."
|
|
3288
|
+
}
|
|
3258
3289
|
},
|
|
3259
3290
|
additionalProperties: false
|
|
3260
3291
|
}
|
|
@@ -3277,7 +3308,10 @@ var MCP_TOOLS = [
|
|
|
3277
3308
|
inputSchema: {
|
|
3278
3309
|
type: "object",
|
|
3279
3310
|
properties: {
|
|
3280
|
-
skill_name: {
|
|
3311
|
+
skill_name: {
|
|
3312
|
+
type: "string",
|
|
3313
|
+
description: "Optional skill name filter."
|
|
3314
|
+
}
|
|
3281
3315
|
},
|
|
3282
3316
|
additionalProperties: false
|
|
3283
3317
|
}
|
|
@@ -3297,8 +3331,14 @@ var MCP_TOOLS = [
|
|
|
3297
3331
|
inputSchema: {
|
|
3298
3332
|
type: "object",
|
|
3299
3333
|
properties: {
|
|
3300
|
-
repo_path: {
|
|
3301
|
-
|
|
3334
|
+
repo_path: {
|
|
3335
|
+
type: "string",
|
|
3336
|
+
description: "Target repository root path."
|
|
3337
|
+
},
|
|
3338
|
+
startup_tax_budget: {
|
|
3339
|
+
type: "number",
|
|
3340
|
+
description: "Optional startup token budget override."
|
|
3341
|
+
}
|
|
3302
3342
|
},
|
|
3303
3343
|
additionalProperties: false
|
|
3304
3344
|
}
|
|
@@ -3309,7 +3349,10 @@ var MCP_TOOLS = [
|
|
|
3309
3349
|
inputSchema: {
|
|
3310
3350
|
type: "object",
|
|
3311
3351
|
properties: {
|
|
3312
|
-
repo_path: {
|
|
3352
|
+
repo_path: {
|
|
3353
|
+
type: "string",
|
|
3354
|
+
description: "Target repository root path."
|
|
3355
|
+
}
|
|
3313
3356
|
},
|
|
3314
3357
|
additionalProperties: false
|
|
3315
3358
|
}
|
|
@@ -3391,7 +3434,9 @@ function handleMcpJsonRpcRequest(request, context) {
|
|
|
3391
3434
|
const skillFilter = typeof args.skill_name === "string" ? args.skill_name : void 0;
|
|
3392
3435
|
payload = evaluateCatalog(context.catalogDir, { skillFilter });
|
|
3393
3436
|
} else if (toolName === "list_catalog_items") {
|
|
3394
|
-
payload = auditCatalogTokenBudgets(context.catalogDir, {
|
|
3437
|
+
payload = auditCatalogTokenBudgets(context.catalogDir, {
|
|
3438
|
+
requireLayout: false
|
|
3439
|
+
});
|
|
3395
3440
|
} else if (toolName === "diagnose_repo") {
|
|
3396
3441
|
const repoPath = typeof args.repo_path === "string" ? args.repo_path : context.repoPath;
|
|
3397
3442
|
const budget = typeof args.startup_tax_budget === "number" ? args.startup_tax_budget : void 0;
|
|
@@ -3596,7 +3641,11 @@ function setupMcpForHarnesses(repoPath, options = {}) {
|
|
|
3596
3641
|
const absPath = path7.join(resolvedRepo, spec.mcpConfigPath);
|
|
3597
3642
|
const exists = fs7.existsSync(absPath) && fs7.statSync(absPath).isFile();
|
|
3598
3643
|
const existingRaw = exists ? fs7.readFileSync(absPath, "utf-8") : null;
|
|
3599
|
-
const updatedRaw = buildUpdatedMcpConfigContent(
|
|
3644
|
+
const updatedRaw = buildUpdatedMcpConfigContent(
|
|
3645
|
+
target,
|
|
3646
|
+
existingRaw,
|
|
3647
|
+
serverName
|
|
3648
|
+
);
|
|
3600
3649
|
let status;
|
|
3601
3650
|
if (!exists) {
|
|
3602
3651
|
status = "created";
|
|
@@ -3616,7 +3665,9 @@ function setupMcpForHarnesses(repoPath, options = {}) {
|
|
|
3616
3665
|
status
|
|
3617
3666
|
});
|
|
3618
3667
|
}
|
|
3619
|
-
const configuredCount = actions.filter(
|
|
3668
|
+
const configuredCount = actions.filter(
|
|
3669
|
+
(a) => a.status !== "unsupported"
|
|
3670
|
+
).length;
|
|
3620
3671
|
return {
|
|
3621
3672
|
repo_path: path7.basename(resolvedRepo) || ".",
|
|
3622
3673
|
dry_run: dryRun,
|
|
@@ -4460,29 +4511,21 @@ function formatSyncReport(report, format = "table", colorEnabled) {
|
|
|
4460
4511
|
(a) => a.action === "created" || a.action === "updated" || a.action === "unchanged"
|
|
4461
4512
|
);
|
|
4462
4513
|
const firstSkill = activeArtifacts.find((a) => a.skill_name !== "codex-agents-index")?.skill_name ?? report.routed_bundle.selected_skills[0]?.name ?? "security-sast-gate";
|
|
4463
|
-
const usageBox = activeArtifacts.length > 0 ?
|
|
4464
|
-
|
|
4465
|
-
|
|
4466
|
-
|
|
4467
|
-
|
|
4468
|
-
` \u2022 ${style.cyan("Deep-Inspect:", c)} Run ${style.green(`npx skillops-cli info ${firstSkill}`, c)} to view triggers & Level 3 scripts`
|
|
4469
|
-
],
|
|
4470
|
-
{
|
|
4471
|
-
title: "\u{1F680} Using Your Skills & Subagents",
|
|
4472
|
-
borderColor: style.cyan,
|
|
4473
|
-
minWidth: 74,
|
|
4474
|
-
colorEnabled: c
|
|
4475
|
-
}
|
|
4514
|
+
const usageBox = activeArtifacts.length > 0 ? renderAiUsageGuide(
|
|
4515
|
+
report.targets,
|
|
4516
|
+
[firstSkill],
|
|
4517
|
+
report.routed_bundle.recommended_subagents,
|
|
4518
|
+
c
|
|
4476
4519
|
) : "";
|
|
4477
4520
|
const nextSteps = renderNextSteps(
|
|
4478
4521
|
[
|
|
4479
4522
|
{
|
|
4480
4523
|
command: `npx skillops-cli info ${firstSkill}`,
|
|
4481
|
-
description: "Inspect triggers, token budget &
|
|
4524
|
+
description: "Inspect triggers, token budget & L3 scripts"
|
|
4482
4525
|
},
|
|
4483
4526
|
{
|
|
4484
4527
|
command: "npx skillops-cli doctor",
|
|
4485
|
-
description: "Verify lockfile SHA-256
|
|
4528
|
+
description: "Verify lockfile SHA-256 & Startup Token Tax"
|
|
4486
4529
|
}
|
|
4487
4530
|
],
|
|
4488
4531
|
c
|
|
@@ -4509,20 +4552,20 @@ var COMMAND_HELP_SPECS = [
|
|
|
4509
4552
|
name: "quickstart",
|
|
4510
4553
|
aliases: ["setup"],
|
|
4511
4554
|
pillar: "library",
|
|
4512
|
-
summary: "1-step onboarding: detect
|
|
4555
|
+
summary: "1-step onboarding: detect, route & sync",
|
|
4513
4556
|
usage: "npx skillops-cli quickstart [options]",
|
|
4514
4557
|
options: [
|
|
4515
4558
|
{
|
|
4516
|
-
flags: "
|
|
4517
|
-
description: "Target repository directory (default:
|
|
4559
|
+
flags: "-p, --project <dir>",
|
|
4560
|
+
description: "Target repository directory (default: cwd)"
|
|
4518
4561
|
},
|
|
4519
4562
|
{
|
|
4520
|
-
flags: "
|
|
4521
|
-
description: "Target AI coding harnesses (
|
|
4563
|
+
flags: "-t, --harness <list|auto|all>",
|
|
4564
|
+
description: "Target AI coding harnesses (claude,cursor...)"
|
|
4522
4565
|
},
|
|
4523
4566
|
{
|
|
4524
4567
|
flags: "--top, --max-skills <n>",
|
|
4525
|
-
description: "
|
|
4568
|
+
description: "Max Skills to activate in bundle (default: 12)"
|
|
4526
4569
|
},
|
|
4527
4570
|
{
|
|
4528
4571
|
flags: "--skip-mcp, --no-mcp",
|
|
@@ -4530,25 +4573,25 @@ var COMMAND_HELP_SPECS = [
|
|
|
4530
4573
|
},
|
|
4531
4574
|
{
|
|
4532
4575
|
flags: "--dry-run",
|
|
4533
|
-
description: "Preview planned changes without writing files
|
|
4576
|
+
description: "Preview planned changes without writing files"
|
|
4534
4577
|
},
|
|
4535
4578
|
{
|
|
4536
4579
|
flags: "--force",
|
|
4537
|
-
description: "Overwrite locally modified artifacts
|
|
4580
|
+
description: "Overwrite locally modified artifacts"
|
|
4538
4581
|
},
|
|
4539
4582
|
{
|
|
4540
|
-
flags: "--format
|
|
4583
|
+
flags: "-f, --format <table|json|md>",
|
|
4541
4584
|
description: "Output report format (default: table)"
|
|
4542
4585
|
}
|
|
4543
4586
|
],
|
|
4544
4587
|
examples: [
|
|
4545
4588
|
{
|
|
4546
4589
|
command: "npx skillops-cli quickstart",
|
|
4547
|
-
description: "Auto-detect stack
|
|
4590
|
+
description: "Auto-detect stack, sync Skills & wire MCP"
|
|
4548
4591
|
},
|
|
4549
4592
|
{
|
|
4550
|
-
command: "npx skillops-cli quickstart
|
|
4551
|
-
description: "
|
|
4593
|
+
command: "npx skillops-cli quickstart -t cursor,claude --top 6",
|
|
4594
|
+
description: "Sync top 6 Skills to Cursor & Claude Code"
|
|
4552
4595
|
}
|
|
4553
4596
|
]
|
|
4554
4597
|
},
|
|
@@ -4556,7 +4599,7 @@ var COMMAND_HELP_SPECS = [
|
|
|
4556
4599
|
name: "list",
|
|
4557
4600
|
aliases: [],
|
|
4558
4601
|
pillar: "library",
|
|
4559
|
-
summary: "Browse all
|
|
4602
|
+
summary: "Browse all 10 Skills & 9 Subagents",
|
|
4560
4603
|
usage: "npx skillops-cli list [options]",
|
|
4561
4604
|
options: [
|
|
4562
4605
|
{
|
|
@@ -4564,18 +4607,18 @@ var COMMAND_HELP_SPECS = [
|
|
|
4564
4607
|
description: "Custom catalog directory to list"
|
|
4565
4608
|
},
|
|
4566
4609
|
{
|
|
4567
|
-
flags: "--format
|
|
4610
|
+
flags: "-f, --format <table|json|md>",
|
|
4568
4611
|
description: "Output format (default: table)"
|
|
4569
4612
|
}
|
|
4570
4613
|
],
|
|
4571
4614
|
examples: [
|
|
4572
4615
|
{
|
|
4573
4616
|
command: "npx skillops-cli list",
|
|
4574
|
-
description: "Display all 10 Skills
|
|
4617
|
+
description: "Display all 10 Skills & 9 Subagents"
|
|
4575
4618
|
},
|
|
4576
4619
|
{
|
|
4577
4620
|
command: "npx skillops-cli info security-sast-gate",
|
|
4578
|
-
description: "
|
|
4621
|
+
description: "Inspect a specific Skill from the Library"
|
|
4579
4622
|
}
|
|
4580
4623
|
]
|
|
4581
4624
|
},
|
|
@@ -4583,7 +4626,7 @@ var COMMAND_HELP_SPECS = [
|
|
|
4583
4626
|
name: "search",
|
|
4584
4627
|
aliases: ["find"],
|
|
4585
4628
|
pillar: "library",
|
|
4586
|
-
summary: "Search
|
|
4629
|
+
summary: "Search catalog by keyword, stack or domain",
|
|
4587
4630
|
usage: "npx skillops-cli search <query> [options]",
|
|
4588
4631
|
options: [
|
|
4589
4632
|
{
|
|
@@ -4591,18 +4634,18 @@ var COMMAND_HELP_SPECS = [
|
|
|
4591
4634
|
description: "Custom catalog directory to search"
|
|
4592
4635
|
},
|
|
4593
4636
|
{
|
|
4594
|
-
flags: "--format
|
|
4637
|
+
flags: "-f, --format <table|json|md>",
|
|
4595
4638
|
description: "Output format (default: table)"
|
|
4596
4639
|
}
|
|
4597
4640
|
],
|
|
4598
4641
|
examples: [
|
|
4599
4642
|
{
|
|
4600
4643
|
command: "npx skillops-cli search security",
|
|
4601
|
-
description: "Find Skills
|
|
4644
|
+
description: "Find Skills/Subagents matching security/SAST"
|
|
4602
4645
|
},
|
|
4603
4646
|
{
|
|
4604
4647
|
command: "npx skillops-cli find postgres",
|
|
4605
|
-
description: "Find database & PostgreSQL optimization Skills
|
|
4648
|
+
description: "Find database & PostgreSQL optimization Skills"
|
|
4606
4649
|
}
|
|
4607
4650
|
]
|
|
4608
4651
|
},
|
|
@@ -4610,65 +4653,65 @@ var COMMAND_HELP_SPECS = [
|
|
|
4610
4653
|
name: "info",
|
|
4611
4654
|
aliases: ["show", "inspect"],
|
|
4612
4655
|
pillar: "library",
|
|
4613
|
-
summary: "Inspect
|
|
4614
|
-
usage: "npx skillops-cli info <
|
|
4656
|
+
summary: "Inspect triggers, L2 budget & AI usage",
|
|
4657
|
+
usage: "npx skillops-cli info <name> [options]",
|
|
4615
4658
|
options: [
|
|
4616
4659
|
{
|
|
4617
4660
|
flags: "--catalog <dir>",
|
|
4618
4661
|
description: "Custom catalog directory"
|
|
4619
4662
|
},
|
|
4620
4663
|
{
|
|
4621
|
-
flags: "--format
|
|
4664
|
+
flags: "-f, --format <table|json|md>",
|
|
4622
4665
|
description: "Output format (default: table)"
|
|
4623
4666
|
}
|
|
4624
4667
|
],
|
|
4625
4668
|
examples: [
|
|
4626
4669
|
{
|
|
4627
4670
|
command: "npx skillops-cli info bug-reproducer-tdd",
|
|
4628
|
-
description: "Inspect
|
|
4671
|
+
description: "Inspect triggers, L3 scripts & IDE invocation"
|
|
4629
4672
|
},
|
|
4630
4673
|
{
|
|
4631
4674
|
command: "npx skillops-cli show red-team-breaker",
|
|
4632
|
-
description: "Inspect the red-team-breaker
|
|
4675
|
+
description: "Inspect the red-team-breaker Subagent card"
|
|
4633
4676
|
}
|
|
4634
4677
|
]
|
|
4635
4678
|
},
|
|
4636
4679
|
{
|
|
4637
4680
|
name: "add",
|
|
4638
|
-
aliases: ["install"
|
|
4681
|
+
aliases: ["install"],
|
|
4639
4682
|
pillar: "library",
|
|
4640
|
-
summary: "Install
|
|
4683
|
+
summary: "Install Skills/Subagents into AI harnesses",
|
|
4641
4684
|
usage: "npx skillops-cli add <name...> [options]",
|
|
4642
4685
|
options: [
|
|
4643
4686
|
{
|
|
4644
|
-
flags: "
|
|
4687
|
+
flags: "-p, --project <dir>",
|
|
4645
4688
|
description: "Target repository directory"
|
|
4646
4689
|
},
|
|
4647
4690
|
{
|
|
4648
|
-
flags: "
|
|
4649
|
-
description: "Target AI
|
|
4691
|
+
flags: "-t, --harness <list|auto|all>",
|
|
4692
|
+
description: "Target AI harnesses (claude,cursor,all...)"
|
|
4650
4693
|
},
|
|
4651
4694
|
{
|
|
4652
4695
|
flags: "--dry-run",
|
|
4653
|
-
description: "Preview planned
|
|
4696
|
+
description: "Preview planned writes without modifying disk"
|
|
4654
4697
|
},
|
|
4655
4698
|
{
|
|
4656
4699
|
flags: "--force",
|
|
4657
4700
|
description: "Overwrite locally drifted files"
|
|
4658
4701
|
},
|
|
4659
4702
|
{
|
|
4660
|
-
flags: "--format
|
|
4703
|
+
flags: "-f, --format <table|json|md>",
|
|
4661
4704
|
description: "Output format (default: table)"
|
|
4662
4705
|
}
|
|
4663
4706
|
],
|
|
4664
4707
|
examples: [
|
|
4665
4708
|
{
|
|
4666
4709
|
command: "npx skillops-cli install security-sast-gate",
|
|
4667
|
-
description: "Install
|
|
4710
|
+
description: "Install security-sast-gate into harnesses"
|
|
4668
4711
|
},
|
|
4669
4712
|
{
|
|
4670
|
-
command: "npx skillops-cli add mcp-architect
|
|
4671
|
-
description: "Install
|
|
4713
|
+
command: "npx skillops-cli add mcp-architect -t claude,cursor",
|
|
4714
|
+
description: "Install mcp-architect into Claude & Cursor"
|
|
4672
4715
|
}
|
|
4673
4716
|
]
|
|
4674
4717
|
},
|
|
@@ -4676,26 +4719,26 @@ var COMMAND_HELP_SPECS = [
|
|
|
4676
4719
|
name: "remove",
|
|
4677
4720
|
aliases: ["uninstall", "rm"],
|
|
4678
4721
|
pillar: "library",
|
|
4679
|
-
summary: "
|
|
4722
|
+
summary: "Remove a Skill/Subagent from harnesses",
|
|
4680
4723
|
usage: "npx skillops-cli remove <name...> [options]",
|
|
4681
4724
|
options: [
|
|
4682
4725
|
{
|
|
4683
|
-
flags: "
|
|
4726
|
+
flags: "-p, --project <dir>",
|
|
4684
4727
|
description: "Target repository directory"
|
|
4685
4728
|
},
|
|
4686
4729
|
{
|
|
4687
|
-
flags: "
|
|
4730
|
+
flags: "-t, --harness <list>",
|
|
4688
4731
|
description: "Restrict removal to specific harnesses"
|
|
4689
4732
|
},
|
|
4690
4733
|
{
|
|
4691
4734
|
flags: "--force",
|
|
4692
|
-
description: "Remove even if
|
|
4735
|
+
description: "Remove even if SHA-256 drift is detected"
|
|
4693
4736
|
}
|
|
4694
4737
|
],
|
|
4695
4738
|
examples: [
|
|
4696
4739
|
{
|
|
4697
4740
|
command: "npx skillops-cli uninstall mcp-architect",
|
|
4698
|
-
description: "Remove
|
|
4741
|
+
description: "Remove runtime files & update lockfile"
|
|
4699
4742
|
}
|
|
4700
4743
|
]
|
|
4701
4744
|
},
|
|
@@ -4703,16 +4746,16 @@ var COMMAND_HELP_SPECS = [
|
|
|
4703
4746
|
name: "route",
|
|
4704
4747
|
aliases: ["recommend"],
|
|
4705
4748
|
pillar: "library",
|
|
4706
|
-
summary: "
|
|
4749
|
+
summary: "Recommend optimal <=12 Skill bundle",
|
|
4707
4750
|
usage: "npx skillops-cli recommend [options]",
|
|
4708
4751
|
options: [
|
|
4709
4752
|
{
|
|
4710
|
-
flags: "
|
|
4753
|
+
flags: "-p, --project <dir>",
|
|
4711
4754
|
description: "Repository directory to fingerprint"
|
|
4712
4755
|
},
|
|
4713
4756
|
{
|
|
4714
4757
|
flags: "--task <prompt>",
|
|
4715
|
-
description: "
|
|
4758
|
+
description: "Task prompt to boost task-specific Skills"
|
|
4716
4759
|
},
|
|
4717
4760
|
{
|
|
4718
4761
|
flags: "--top, --max-skills <n>",
|
|
@@ -4720,21 +4763,21 @@ var COMMAND_HELP_SPECS = [
|
|
|
4720
4763
|
},
|
|
4721
4764
|
{
|
|
4722
4765
|
flags: "--max-l1-tokens <n>",
|
|
4723
|
-
description: "Maximum
|
|
4766
|
+
description: "Maximum L1 routing token budget (default: 1500)"
|
|
4724
4767
|
},
|
|
4725
4768
|
{
|
|
4726
|
-
flags: "--format
|
|
4769
|
+
flags: "-f, --format <table|json|md>",
|
|
4727
4770
|
description: "Output format (default: table)"
|
|
4728
4771
|
}
|
|
4729
4772
|
],
|
|
4730
4773
|
examples: [
|
|
4731
4774
|
{
|
|
4732
4775
|
command: "npx skillops-cli recommend",
|
|
4733
|
-
description: "Recommend
|
|
4776
|
+
description: "Recommend best Skills for current repo stack"
|
|
4734
4777
|
},
|
|
4735
4778
|
{
|
|
4736
|
-
command: 'npx skillops-cli route --task "
|
|
4737
|
-
description: "Route top 4 Skills
|
|
4779
|
+
command: 'npx skillops-cli route --task "slow postgres" --top 4',
|
|
4780
|
+
description: "Route top 4 Skills for a specific task"
|
|
4738
4781
|
}
|
|
4739
4782
|
]
|
|
4740
4783
|
},
|
|
@@ -4742,12 +4785,12 @@ var COMMAND_HELP_SPECS = [
|
|
|
4742
4785
|
name: "create",
|
|
4743
4786
|
aliases: ["new"],
|
|
4744
4787
|
pillar: "framework",
|
|
4745
|
-
summary: "Scaffold
|
|
4746
|
-
usage: "npx skillops-cli create <skill|subagent> <
|
|
4788
|
+
summary: "Scaffold custom Skill or Subagent template",
|
|
4789
|
+
usage: "npx skillops-cli create <skill|subagent> <name> [options]",
|
|
4747
4790
|
options: [
|
|
4748
4791
|
{
|
|
4749
|
-
flags: "--description
|
|
4750
|
-
description: "Custom trigger description (
|
|
4792
|
+
flags: "-d, --description <text>",
|
|
4793
|
+
description: "Custom trigger description (INV-SKILL-01..04)"
|
|
4751
4794
|
},
|
|
4752
4795
|
{
|
|
4753
4796
|
flags: "--catalog <dir>",
|
|
@@ -4758,18 +4801,18 @@ var COMMAND_HELP_SPECS = [
|
|
|
4758
4801
|
description: "Overwrite existing Skill or Subagent template"
|
|
4759
4802
|
},
|
|
4760
4803
|
{
|
|
4761
|
-
flags: "--format
|
|
4804
|
+
flags: "-f, --format <table|json|md>",
|
|
4762
4805
|
description: "Output format (default: table)"
|
|
4763
4806
|
}
|
|
4764
4807
|
],
|
|
4765
4808
|
examples: [
|
|
4766
4809
|
{
|
|
4767
4810
|
command: "npx skillops-cli create skill graphql-schema-guard",
|
|
4768
|
-
description: "Scaffold a new
|
|
4811
|
+
description: "Scaffold a new Skill with L3 script & evals"
|
|
4769
4812
|
},
|
|
4770
4813
|
{
|
|
4771
4814
|
command: "npx skillops-cli create subagent migration-reviewer",
|
|
4772
|
-
description: "Scaffold a new
|
|
4815
|
+
description: "Scaffold a new Context-Isolated Subagent"
|
|
4773
4816
|
}
|
|
4774
4817
|
]
|
|
4775
4818
|
},
|
|
@@ -4777,7 +4820,7 @@ var COMMAND_HELP_SPECS = [
|
|
|
4777
4820
|
name: "audit",
|
|
4778
4821
|
aliases: [],
|
|
4779
4822
|
pillar: "framework",
|
|
4780
|
-
summary: "
|
|
4823
|
+
summary: "Verify L1/L2 budgets & TF-IDF collisions",
|
|
4781
4824
|
usage: "npx skillops-cli audit [options]",
|
|
4782
4825
|
options: [
|
|
4783
4826
|
{
|
|
@@ -4786,21 +4829,21 @@ var COMMAND_HELP_SPECS = [
|
|
|
4786
4829
|
},
|
|
4787
4830
|
{
|
|
4788
4831
|
flags: "--require-layout",
|
|
4789
|
-
description: "Enforce
|
|
4832
|
+
description: "Enforce evals/evals.json and L3 scripts"
|
|
4790
4833
|
},
|
|
4791
4834
|
{
|
|
4792
4835
|
flags: "--strict",
|
|
4793
|
-
description: "Fail
|
|
4836
|
+
description: "Fail on HIGH_RISK as well as BLOCKING collisions"
|
|
4794
4837
|
},
|
|
4795
4838
|
{
|
|
4796
|
-
flags: "--format
|
|
4839
|
+
flags: "-f, --format <table|json|gh>",
|
|
4797
4840
|
description: "Output format (default: table)"
|
|
4798
4841
|
}
|
|
4799
4842
|
],
|
|
4800
4843
|
examples: [
|
|
4801
4844
|
{
|
|
4802
4845
|
command: "npx skillops-cli audit --require-layout --strict",
|
|
4803
|
-
description: "Certify
|
|
4846
|
+
description: "Certify token budgets & zero collisions"
|
|
4804
4847
|
}
|
|
4805
4848
|
]
|
|
4806
4849
|
},
|
|
@@ -4808,7 +4851,7 @@ var COMMAND_HELP_SPECS = [
|
|
|
4808
4851
|
name: "eval",
|
|
4809
4852
|
aliases: [],
|
|
4810
4853
|
pillar: "framework",
|
|
4811
|
-
summary: "
|
|
4854
|
+
summary: "Run deterministic A/B TDD benchmarks",
|
|
4812
4855
|
usage: "npx skillops-cli eval [options]",
|
|
4813
4856
|
options: [
|
|
4814
4857
|
{
|
|
@@ -4821,25 +4864,25 @@ var COMMAND_HELP_SPECS = [
|
|
|
4821
4864
|
},
|
|
4822
4865
|
{
|
|
4823
4866
|
flags: "--out <file>",
|
|
4824
|
-
description: "Write
|
|
4867
|
+
description: "Write benchmark report (HTML/Markdown) to disk"
|
|
4825
4868
|
},
|
|
4826
4869
|
{
|
|
4827
4870
|
flags: "--strict",
|
|
4828
|
-
description: "Exit
|
|
4871
|
+
description: "Exit 4 if any Skill fails CERTIFIED_IMPROVEMENT"
|
|
4829
4872
|
},
|
|
4830
4873
|
{
|
|
4831
|
-
flags: "--format
|
|
4874
|
+
flags: "-f, --format <table|json|html>",
|
|
4832
4875
|
description: "Output format (default: table)"
|
|
4833
4876
|
}
|
|
4834
4877
|
],
|
|
4835
4878
|
examples: [
|
|
4836
4879
|
{
|
|
4837
4880
|
command: "npx skillops-cli eval --strict",
|
|
4838
|
-
description: "Run deterministic A/B evals across
|
|
4881
|
+
description: "Run deterministic A/B evals across catalog"
|
|
4839
4882
|
},
|
|
4840
4883
|
{
|
|
4841
|
-
command: "npx skillops-cli eval
|
|
4842
|
-
description: "Export
|
|
4884
|
+
command: "npx skillops-cli eval -f html --out benchmark.html",
|
|
4885
|
+
description: "Export standalone HTML benchmark dashboard"
|
|
4843
4886
|
}
|
|
4844
4887
|
]
|
|
4845
4888
|
},
|
|
@@ -4847,22 +4890,22 @@ var COMMAND_HELP_SPECS = [
|
|
|
4847
4890
|
name: "init",
|
|
4848
4891
|
aliases: [],
|
|
4849
4892
|
pillar: "runtime",
|
|
4850
|
-
summary: "
|
|
4893
|
+
summary: "Create .skillops.yml and detect harnesses",
|
|
4851
4894
|
usage: "npx skillops-cli init [options]",
|
|
4852
4895
|
options: [
|
|
4853
4896
|
{
|
|
4854
|
-
flags: "
|
|
4897
|
+
flags: "-p, --project <dir>",
|
|
4855
4898
|
description: "Target repository directory"
|
|
4856
4899
|
},
|
|
4857
4900
|
{
|
|
4858
|
-
flags: "
|
|
4859
|
-
description: "Initial target harnesses
|
|
4901
|
+
flags: "-t, --harness <list|auto|all>",
|
|
4902
|
+
description: "Initial target harnesses for .skillops.yml"
|
|
4860
4903
|
}
|
|
4861
4904
|
],
|
|
4862
4905
|
examples: [
|
|
4863
4906
|
{
|
|
4864
4907
|
command: "npx skillops-cli init",
|
|
4865
|
-
description: "Create .skillops.yml with
|
|
4908
|
+
description: "Create .skillops.yml with detected harnesses"
|
|
4866
4909
|
}
|
|
4867
4910
|
]
|
|
4868
4911
|
},
|
|
@@ -4870,16 +4913,16 @@ var COMMAND_HELP_SPECS = [
|
|
|
4870
4913
|
name: "sync",
|
|
4871
4914
|
aliases: [],
|
|
4872
4915
|
pillar: "runtime",
|
|
4873
|
-
summary: "Transpile
|
|
4916
|
+
summary: "Transpile bundle across 20 AI agents",
|
|
4874
4917
|
usage: "npx skillops-cli sync [options]",
|
|
4875
4918
|
options: [
|
|
4876
4919
|
{
|
|
4877
|
-
flags: "
|
|
4920
|
+
flags: "-p, --project <dir>",
|
|
4878
4921
|
description: "Target repository directory"
|
|
4879
4922
|
},
|
|
4880
4923
|
{
|
|
4881
|
-
flags: "
|
|
4882
|
-
description: "Target AI
|
|
4924
|
+
flags: "-t, --harness <list|auto|all>",
|
|
4925
|
+
description: "Target AI harnesses (default: .skillops.yml)"
|
|
4883
4926
|
},
|
|
4884
4927
|
{
|
|
4885
4928
|
flags: "--top, --max-skills <n>",
|
|
@@ -4887,7 +4930,7 @@ var COMMAND_HELP_SPECS = [
|
|
|
4887
4930
|
},
|
|
4888
4931
|
{
|
|
4889
4932
|
flags: "--dry-run",
|
|
4890
|
-
description: "Preview planned artifacts without writing
|
|
4933
|
+
description: "Preview planned artifacts without writing"
|
|
4891
4934
|
},
|
|
4892
4935
|
{
|
|
4893
4936
|
flags: "--force",
|
|
@@ -4897,11 +4940,11 @@ var COMMAND_HELP_SPECS = [
|
|
|
4897
4940
|
examples: [
|
|
4898
4941
|
{
|
|
4899
4942
|
command: "npx skillops-cli sync --auto",
|
|
4900
|
-
description: "Sync
|
|
4943
|
+
description: "Sync bundle into all detected AI harnesses"
|
|
4901
4944
|
},
|
|
4902
4945
|
{
|
|
4903
4946
|
command: "npx skillops-cli sync --harness all",
|
|
4904
|
-
description: "Transpile across all 20 supported AI
|
|
4947
|
+
description: "Transpile across all 20 supported AI agents"
|
|
4905
4948
|
}
|
|
4906
4949
|
]
|
|
4907
4950
|
},
|
|
@@ -4909,11 +4952,11 @@ var COMMAND_HELP_SPECS = [
|
|
|
4909
4952
|
name: "clean",
|
|
4910
4953
|
aliases: [],
|
|
4911
4954
|
pillar: "runtime",
|
|
4912
|
-
summary: "Remove all
|
|
4955
|
+
summary: "Remove all tracked runtime artifacts",
|
|
4913
4956
|
usage: "npx skillops-cli clean [options]",
|
|
4914
4957
|
options: [
|
|
4915
4958
|
{
|
|
4916
|
-
flags: "
|
|
4959
|
+
flags: "-p, --project <dir>",
|
|
4917
4960
|
description: "Target repository directory"
|
|
4918
4961
|
},
|
|
4919
4962
|
{
|
|
@@ -4928,7 +4971,7 @@ var COMMAND_HELP_SPECS = [
|
|
|
4928
4971
|
examples: [
|
|
4929
4972
|
{
|
|
4930
4973
|
command: "npx skillops-cli clean",
|
|
4931
|
-
description: "
|
|
4974
|
+
description: "Remove all synced artifacts & lockfile"
|
|
4932
4975
|
}
|
|
4933
4976
|
]
|
|
4934
4977
|
},
|
|
@@ -4936,11 +4979,11 @@ var COMMAND_HELP_SPECS = [
|
|
|
4936
4979
|
name: "tokens",
|
|
4937
4980
|
aliases: ["budget"],
|
|
4938
4981
|
pillar: "runtime",
|
|
4939
|
-
summary: "Analyze
|
|
4982
|
+
summary: "Analyze Startup Token Tax & context bloat",
|
|
4940
4983
|
usage: "npx skillops-cli budget [options]",
|
|
4941
4984
|
options: [
|
|
4942
4985
|
{
|
|
4943
|
-
flags: "
|
|
4986
|
+
flags: "-p, --project <dir>",
|
|
4944
4987
|
description: "Repository directory to inspect"
|
|
4945
4988
|
},
|
|
4946
4989
|
{
|
|
@@ -4949,17 +4992,17 @@ var COMMAND_HELP_SPECS = [
|
|
|
4949
4992
|
},
|
|
4950
4993
|
{
|
|
4951
4994
|
flags: "--strict",
|
|
4952
|
-
description: "
|
|
4995
|
+
description: "Exit 3 if Startup Token Tax exceeds budget"
|
|
4953
4996
|
},
|
|
4954
4997
|
{
|
|
4955
|
-
flags: "--format
|
|
4998
|
+
flags: "-f, --format <table|json|md>",
|
|
4956
4999
|
description: "Output format (default: table)"
|
|
4957
5000
|
}
|
|
4958
5001
|
],
|
|
4959
5002
|
examples: [
|
|
4960
5003
|
{
|
|
4961
5004
|
command: "npx skillops-cli budget",
|
|
4962
|
-
description: "Inspect repository Startup Token Tax
|
|
5005
|
+
description: "Inspect repository Startup Token Tax & savings"
|
|
4963
5006
|
}
|
|
4964
5007
|
]
|
|
4965
5008
|
},
|
|
@@ -4967,11 +5010,11 @@ var COMMAND_HELP_SPECS = [
|
|
|
4967
5010
|
name: "doctor",
|
|
4968
5011
|
aliases: ["status"],
|
|
4969
5012
|
pillar: "runtime",
|
|
4970
|
-
summary: "Diagnose
|
|
5013
|
+
summary: "Diagnose environment, drift & token budget",
|
|
4971
5014
|
usage: "npx skillops-cli doctor [options]",
|
|
4972
5015
|
options: [
|
|
4973
5016
|
{
|
|
4974
|
-
flags: "
|
|
5017
|
+
flags: "-p, --project <dir>",
|
|
4975
5018
|
description: "Repository directory to diagnose"
|
|
4976
5019
|
},
|
|
4977
5020
|
{
|
|
@@ -4979,7 +5022,7 @@ var COMMAND_HELP_SPECS = [
|
|
|
4979
5022
|
description: "Fail on warnings as well as errors"
|
|
4980
5023
|
},
|
|
4981
5024
|
{
|
|
4982
|
-
flags: "--format
|
|
5025
|
+
flags: "-f, --format <table|json|md>",
|
|
4983
5026
|
description: "Output format (default: table)"
|
|
4984
5027
|
}
|
|
4985
5028
|
],
|
|
@@ -4994,22 +5037,22 @@ var COMMAND_HELP_SPECS = [
|
|
|
4994
5037
|
name: "harnesses",
|
|
4995
5038
|
aliases: [],
|
|
4996
5039
|
pillar: "runtime",
|
|
4997
|
-
summary: "List
|
|
5040
|
+
summary: "List 20 supported AI agents & repo status",
|
|
4998
5041
|
usage: "npx skillops-cli harnesses [options]",
|
|
4999
5042
|
options: [
|
|
5000
5043
|
{
|
|
5001
|
-
flags: "
|
|
5044
|
+
flags: "-p, --project <dir>",
|
|
5002
5045
|
description: "Repository directory to scan for AI harnesses"
|
|
5003
5046
|
},
|
|
5004
5047
|
{
|
|
5005
|
-
flags: "--format
|
|
5048
|
+
flags: "-f, --format <table|json|md>",
|
|
5006
5049
|
description: "Output format (default: table)"
|
|
5007
5050
|
}
|
|
5008
5051
|
],
|
|
5009
5052
|
examples: [
|
|
5010
5053
|
{
|
|
5011
5054
|
command: "npx skillops-cli harnesses",
|
|
5012
|
-
description: "View all 20 supported AI
|
|
5055
|
+
description: "View all 20 supported AI IDEs/CLI agents"
|
|
5013
5056
|
}
|
|
5014
5057
|
]
|
|
5015
5058
|
},
|
|
@@ -5017,15 +5060,15 @@ var COMMAND_HELP_SPECS = [
|
|
|
5017
5060
|
name: "mcp-setup",
|
|
5018
5061
|
aliases: [],
|
|
5019
5062
|
pillar: "runtime",
|
|
5020
|
-
summary: "
|
|
5063
|
+
summary: "Wire MCP server across 13 AI IDEs & agents",
|
|
5021
5064
|
usage: "npx skillops-cli mcp-setup [options]",
|
|
5022
5065
|
options: [
|
|
5023
5066
|
{
|
|
5024
|
-
flags: "
|
|
5067
|
+
flags: "-p, --project <dir>",
|
|
5025
5068
|
description: "Target repository directory"
|
|
5026
5069
|
},
|
|
5027
5070
|
{
|
|
5028
|
-
flags: "
|
|
5071
|
+
flags: "-t, --harness <list|auto|all>",
|
|
5029
5072
|
description: "Target harnesses to configure MCP for"
|
|
5030
5073
|
},
|
|
5031
5074
|
{
|
|
@@ -5036,7 +5079,7 @@ var COMMAND_HELP_SPECS = [
|
|
|
5036
5079
|
examples: [
|
|
5037
5080
|
{
|
|
5038
5081
|
command: "npx skillops-cli mcp-setup --auto",
|
|
5039
|
-
description: "
|
|
5082
|
+
description: "Wire SkillOps MCP into detected IDEs"
|
|
5040
5083
|
}
|
|
5041
5084
|
]
|
|
5042
5085
|
},
|
|
@@ -5044,18 +5087,18 @@ var COMMAND_HELP_SPECS = [
|
|
|
5044
5087
|
name: "mcp",
|
|
5045
5088
|
aliases: [],
|
|
5046
5089
|
pillar: "runtime",
|
|
5047
|
-
summary: "Start
|
|
5090
|
+
summary: "Start stdio JSON-RPC 2.0 MCP server",
|
|
5048
5091
|
usage: "npx skillops-cli mcp [options]",
|
|
5049
5092
|
options: [
|
|
5050
5093
|
{
|
|
5051
|
-
flags: "
|
|
5094
|
+
flags: "-p, --project <dir>",
|
|
5052
5095
|
description: "Repository root served over MCP"
|
|
5053
5096
|
}
|
|
5054
5097
|
],
|
|
5055
5098
|
examples: [
|
|
5056
5099
|
{
|
|
5057
5100
|
command: "npx skillops-cli mcp",
|
|
5058
|
-
description: "Start stdio MCP server
|
|
5101
|
+
description: "Start stdio MCP server for AI IDEs"
|
|
5059
5102
|
}
|
|
5060
5103
|
]
|
|
5061
5104
|
}
|
|
@@ -5068,117 +5111,69 @@ function findCommandHelpSpec(commandOrAlias) {
|
|
|
5068
5111
|
}
|
|
5069
5112
|
function renderGlobalHelp(version, colorEnabled) {
|
|
5070
5113
|
const c = colorEnabled;
|
|
5114
|
+
const bar = style.dim("\u2502", c);
|
|
5071
5115
|
const banner = renderHeaderBanner(
|
|
5072
|
-
"
|
|
5116
|
+
"Framework & Library for AI Skills & Subagents",
|
|
5073
5117
|
{
|
|
5074
5118
|
version,
|
|
5075
5119
|
colorEnabled: c
|
|
5076
5120
|
}
|
|
5077
5121
|
);
|
|
5078
|
-
const quickstartBox = renderBox(
|
|
5079
|
-
[
|
|
5080
|
-
`${style.bold(style.green("npx skillops-cli quickstart", c), c)} ${style.dim("# 1-step setup: detect stack, install Skills/Subagents & wire MCP", c)}`,
|
|
5081
|
-
`${style.bold(style.cyan("npx skillops-cli info <name>", c), c)} ${style.dim("# Inspect any Skill/Subagent & see how to invoke it in your AI", c)}`,
|
|
5082
|
-
`${style.bold(style.magenta("npx skillops-cli create skill <name>", c), c)} ${style.dim("# Scaffold your own custom Skill using the SkillOps Framework", c)}`
|
|
5083
|
-
],
|
|
5084
|
-
{
|
|
5085
|
-
title: "\u{1F680} 10-Second Quickstart (Library + Framework)",
|
|
5086
|
-
borderColor: style.cyan,
|
|
5087
|
-
minWidth: 88,
|
|
5088
|
-
colorEnabled: c
|
|
5089
|
-
}
|
|
5090
|
-
);
|
|
5091
5122
|
const formatCmdSection = (pillar) => {
|
|
5092
5123
|
const specs = COMMAND_HELP_SPECS.filter((s) => s.pillar === pillar);
|
|
5093
|
-
return
|
|
5094
|
-
|
|
5095
|
-
|
|
5096
|
-
style.bold(style.cyan(s.name, c), c)
|
|
5097
|
-
|
|
5098
|
-
|
|
5099
|
-
|
|
5100
|
-
{
|
|
5101
|
-
);
|
|
5124
|
+
return specs.map((s) => {
|
|
5125
|
+
const aliasPart = s.aliases.length > 0 ? style.dim(` (${s.aliases.join(", ")})`, c) : "";
|
|
5126
|
+
const cmdCol = padVisible(
|
|
5127
|
+
`${style.bold(style.cyan(s.name, c), c)}${aliasPart}`,
|
|
5128
|
+
23,
|
|
5129
|
+
"left"
|
|
5130
|
+
);
|
|
5131
|
+
return `${bar} ${cmdCol}${s.summary}`;
|
|
5132
|
+
}).join("\n");
|
|
5102
5133
|
};
|
|
5103
|
-
const globalFlagsTable = renderTable(
|
|
5104
|
-
["Global Flag", "Description"],
|
|
5105
|
-
[
|
|
5106
|
-
[
|
|
5107
|
-
style.cyan("--project, --repo, -p <dir>", c),
|
|
5108
|
-
"Target project/repository directory (default: current working directory)"
|
|
5109
|
-
],
|
|
5110
|
-
[
|
|
5111
|
-
style.cyan("--harness, --targets, -t <list|auto|all>", c),
|
|
5112
|
-
"Target AI coding harnesses (e.g. claude,cursor,windsurf,copilot or auto/all)"
|
|
5113
|
-
],
|
|
5114
|
-
[
|
|
5115
|
-
style.cyan("--format, -f <table|json|markdown|github>", c),
|
|
5116
|
-
"Output format for reports and CI pipelines (default: table)"
|
|
5117
|
-
],
|
|
5118
|
-
[
|
|
5119
|
-
style.cyan("--help, -h / --version, -V", c),
|
|
5120
|
-
"Show global or per-command help (`npx skillops-cli <cmd> --help`) / CLI version"
|
|
5121
|
-
]
|
|
5122
|
-
],
|
|
5123
|
-
{ colorEnabled: c, indent: 2 }
|
|
5124
|
-
);
|
|
5125
5134
|
return [
|
|
5126
|
-
`SkillOps v${version} \u2014 The Zero-API NPX Engine for High-End AI Skills & Subagents`,
|
|
5127
|
-
"Usage: npx skillops-cli <command> [options]",
|
|
5128
|
-
"",
|
|
5129
5135
|
banner,
|
|
5130
|
-
|
|
5131
|
-
renderSectionHeader(
|
|
5132
|
-
|
|
5133
|
-
|
|
5134
|
-
),
|
|
5136
|
+
`${bar} Usage: npx skillops-cli <command> [options]`,
|
|
5137
|
+
renderSectionHeader("Quickstart (Library + Framework)", c),
|
|
5138
|
+
`${bar} ${style.dim("$", c)} ${style.bold(style.green("npx skillops-cli quickstart", c), c)} ${style.dim("\u2014 Detect stack, sync Skills & MCP", c)}`,
|
|
5139
|
+
`${bar} ${style.dim("$", c)} ${style.bold(style.cyan("npx skillops-cli info <name>", c), c)} ${style.dim("\u2014 Inspect Skill/Subagent & usage", c)}`,
|
|
5140
|
+
`${bar} ${style.dim("$", c)} ${style.bold(style.magenta("npx skillops-cli create skill <name>", c), c)} ${style.dim("\u2014 Scaffold a custom Skill", c)}`,
|
|
5141
|
+
renderSectionHeader("1. Library of High-End Skills & Subagents", c),
|
|
5135
5142
|
formatCmdSection("library"),
|
|
5136
5143
|
renderSectionHeader(
|
|
5137
|
-
"
|
|
5144
|
+
"2. Framework for Building Custom Skills & Subagents",
|
|
5138
5145
|
c
|
|
5139
5146
|
),
|
|
5140
5147
|
formatCmdSection("framework"),
|
|
5141
5148
|
renderSectionHeader(
|
|
5142
|
-
"
|
|
5149
|
+
"3. Universal Runtime Sync, Token Economy & Diagnostics",
|
|
5143
5150
|
c
|
|
5144
5151
|
),
|
|
5145
5152
|
formatCmdSection("runtime"),
|
|
5146
|
-
|
|
5147
|
-
|
|
5148
|
-
"",
|
|
5149
|
-
` ${style.dim("\u{1F4A1} Tip: Run", c)} ${style.bold(style.cyan("npx skillops-cli <command> --help", c), c)} ${style.dim("for detailed flags and copy-paste examples.", c)}`,
|
|
5150
|
-
""
|
|
5153
|
+
bar,
|
|
5154
|
+
`${style.dim("\u2570\u2500", c)} ${style.bold("Global Flags:", c)} ${style.cyan("-p <dir>", c)} \xB7 ${style.cyan("-t <harnesses>", c)} \xB7 ${style.cyan("-f <table|json|md>", c)} \xB7 ${style.cyan("-h <cmd>", c)}`
|
|
5151
5155
|
].join("\n");
|
|
5152
5156
|
}
|
|
5153
5157
|
function renderCommandHelp(spec, version, colorEnabled) {
|
|
5154
5158
|
const c = colorEnabled;
|
|
5159
|
+
const bar = style.dim("\u2502", c);
|
|
5155
5160
|
const pillarBadge = spec.pillar === "library" ? formatBadge("info", "LIBRARY", c) : spec.pillar === "framework" ? formatBadge("pass", "FRAMEWORK", c) : formatBadge("subagent", "RUNTIME", c);
|
|
5156
5161
|
const aliasText = spec.aliases.length > 0 ? ` (aliases: ${spec.aliases.map((a) => style.cyan(a, c)).join(", ")})` : "";
|
|
5157
|
-
const
|
|
5158
|
-
|
|
5159
|
-
|
|
5160
|
-
|
|
5161
|
-
|
|
5162
|
-
"",
|
|
5163
|
-
`${style.bold("Usage:", c)} ${style.green(spec.usage, c)}`
|
|
5164
|
-
],
|
|
5165
|
-
{
|
|
5166
|
-
title: `SkillOps v${version} \u2014 Command Reference`,
|
|
5167
|
-
borderColor: style.cyan,
|
|
5168
|
-
minWidth: 78,
|
|
5169
|
-
colorEnabled: c
|
|
5170
|
-
}
|
|
5171
|
-
);
|
|
5162
|
+
const headerLines = [
|
|
5163
|
+
`${style.bold(style.cyan(`\u25C6 SkillOps v${version}`, c), c)} ${style.dim("\u2014", c)} ${style.bold(`skillops ${spec.name}`, c)}${aliasText} ${pillarBadge}`,
|
|
5164
|
+
`${bar} ${spec.summary}`,
|
|
5165
|
+
`${bar} ${style.bold("Usage:", c)} ${style.green(spec.usage, c)}`
|
|
5166
|
+
].join("\n");
|
|
5172
5167
|
const optionsSection = spec.options.length > 0 ? [
|
|
5173
5168
|
renderSectionHeader("Options & Flags", c),
|
|
5174
5169
|
renderTable(
|
|
5175
5170
|
["Flag", "Description"],
|
|
5176
5171
|
spec.options.map((o) => [style.cyan(o.flags, c), o.description]),
|
|
5177
|
-
{ colorEnabled: c, indent:
|
|
5172
|
+
{ colorEnabled: c, indent: 3 }
|
|
5178
5173
|
)
|
|
5179
5174
|
].join("\n") : "";
|
|
5180
5175
|
const examplesSection = renderNextSteps(spec.examples, c);
|
|
5181
|
-
return [
|
|
5176
|
+
return [headerLines, optionsSection, examplesSection].filter(Boolean).join("\n");
|
|
5182
5177
|
}
|
|
5183
5178
|
|
|
5184
5179
|
// src/framework/index.ts
|
|
@@ -5280,71 +5275,66 @@ function formatCatalogItemInfo(info, format = "table", colorEnabled) {
|
|
|
5280
5275
|
return lines.join("\n");
|
|
5281
5276
|
}
|
|
5282
5277
|
const c = colorEnabled;
|
|
5278
|
+
const bar = style.dim("\u2502", c);
|
|
5283
5279
|
const badge = info.kind === "skill" ? formatBadge("skill", "HYBRID EXECUTABLE SKILL", c) : formatBadge("subagent", "CONTEXT-ISOLATED SUBAGENT", c);
|
|
5280
|
+
const shortDesc = info.description.length > 68 ? `${info.description.slice(0, 65)}...` : info.description;
|
|
5284
5281
|
const cardLines = [
|
|
5285
|
-
`${
|
|
5286
|
-
|
|
5287
|
-
`${
|
|
5288
|
-
|
|
5289
|
-
""
|
|
5282
|
+
`${style.bold(style.cyan(`\u25C6 SkillOps Library Inspector \u2014 ${info.name}`, c), c)}`,
|
|
5283
|
+
`${bar} ${badge}`,
|
|
5284
|
+
`${bar} ${shortDesc}`,
|
|
5285
|
+
bar
|
|
5290
5286
|
];
|
|
5291
5287
|
if (info.kind === "skill") {
|
|
5292
5288
|
cardLines.push(
|
|
5293
|
-
`${style.bold("Token Economy (INV-SKILL-01..03)
|
|
5294
|
-
|
|
5295
|
-
|
|
5296
|
-
|
|
5297
|
-
|
|
5298
|
-
|
|
5289
|
+
`${style.dim("\u251C\u2500", c)} ${style.bold(style.cyan("Token Economy (INV-SKILL-01..03)", c), c)}`,
|
|
5290
|
+
`${bar} \u2022 L1 Routing : ${style.green(`${info.l1Tokens} tokens`, c)} (<= 160 budget)`,
|
|
5291
|
+
`${bar} \u2022 L2 Playbook : ${info.l2Lines} lines (${info.l2Tokens}t, <= 250 lines)`,
|
|
5292
|
+
`${bar} \u2022 Token Savings : ${style.bold(style.green(`${info.savingsPct}%`, c), c)} Startup Tax saved`,
|
|
5293
|
+
`${bar} \u2022 L3 Scripts (${info.scripts.length}) : ${info.scripts.length > 0 ? style.cyan(info.scripts.join(", "), c) : "none"}`,
|
|
5294
|
+
`${bar} \u2022 TDD Evals : ${info.evalCasesCount} deterministic cases`
|
|
5299
5295
|
);
|
|
5300
5296
|
} else {
|
|
5301
5297
|
cardLines.push(
|
|
5302
|
-
`${style.bold("Context Isolation Contract (INV-SKILL-04)
|
|
5303
|
-
|
|
5304
|
-
|
|
5305
|
-
|
|
5306
|
-
|
|
5298
|
+
`${style.dim("\u251C\u2500", c)} ${style.bold(style.cyan("Context Isolation Contract (INV-SKILL-04)", c), c)}`,
|
|
5299
|
+
`${bar} \u2022 System Prompt : ${style.green(`${info.l1Tokens} tokens`, c)}`,
|
|
5300
|
+
`${bar} \u2022 Max Output Cap : <= ${style.bold(`${info.maxOutputTokens} tokens`, c)}`,
|
|
5301
|
+
`${bar} \u2022 Isolation Mode : ${style.cyan(info.isolation ?? "context-isolated", c)}`,
|
|
5302
|
+
`${bar} \u2022 Allowed Tools : ${info.tools.join(", ")}`
|
|
5307
5303
|
);
|
|
5308
5304
|
}
|
|
5309
5305
|
if (info.headings.length > 0) {
|
|
5310
5306
|
cardLines.push(
|
|
5311
|
-
|
|
5312
|
-
`${style.bold("
|
|
5313
|
-
...info.headings.slice(0,
|
|
5307
|
+
bar,
|
|
5308
|
+
`${style.dim("\u251C\u2500", c)} ${style.bold(style.cyan("Playbook Sections", c), c)}`,
|
|
5309
|
+
...info.headings.slice(0, 5).map((h) => `${bar} \u2022 ${h}`)
|
|
5314
5310
|
);
|
|
5315
5311
|
}
|
|
5316
5312
|
cardLines.push(
|
|
5317
|
-
|
|
5318
|
-
`${style.bold("How to Invoke in Your AI Agent
|
|
5319
|
-
|
|
5320
|
-
info.kind === "skill" ?
|
|
5313
|
+
bar,
|
|
5314
|
+
`${style.dim("\u251C\u2500", c)} ${style.bold(style.cyan("How to Invoke in Your AI Agent", c), c)}`,
|
|
5315
|
+
`${bar} \u2022 ${style.bold("Install:", c)} ${style.green(`npx skillops-cli add ${info.name}`, c)}`,
|
|
5316
|
+
info.kind === "skill" ? `${bar} \u2022 ${style.bold("IDE Chat:", c)} Reference ${style.cyan(`@${info.name}`, c)} or ${style.cyan(`/${info.name}`, c)}` : `${bar} \u2022 ${style.bold("Delegate:", c)} Ask main agent to run ${style.magenta(`@${info.name}`, c)}`
|
|
5321
5317
|
);
|
|
5322
|
-
const box = renderBox(cardLines, {
|
|
5323
|
-
title: `\u{1F4E6} SkillOps Library Inspector \u2014 ${info.name}`,
|
|
5324
|
-
borderColor: info.kind === "skill" ? style.cyan : style.magenta,
|
|
5325
|
-
minWidth: 74,
|
|
5326
|
-
colorEnabled: c
|
|
5327
|
-
});
|
|
5328
5318
|
const nextSteps = renderNextSteps(
|
|
5329
5319
|
[
|
|
5330
5320
|
{
|
|
5331
5321
|
command: `npx skillops-cli add ${info.name}`,
|
|
5332
|
-
description:
|
|
5322
|
+
description: "Install into AI agents"
|
|
5333
5323
|
},
|
|
5334
5324
|
...info.kind === "skill" ? [
|
|
5335
5325
|
{
|
|
5336
5326
|
command: `npx skillops-cli eval --skill ${info.name}`,
|
|
5337
|
-
description:
|
|
5327
|
+
description: "Run TDD benchmark"
|
|
5338
5328
|
}
|
|
5339
5329
|
] : [],
|
|
5340
5330
|
{
|
|
5341
5331
|
command: "npx skillops-cli list",
|
|
5342
|
-
description: "Browse
|
|
5332
|
+
description: "Browse 10 Skills & 9 Subagents"
|
|
5343
5333
|
}
|
|
5344
5334
|
],
|
|
5345
5335
|
c
|
|
5346
5336
|
);
|
|
5347
|
-
return `${
|
|
5337
|
+
return `${cardLines.join("\n")}
|
|
5348
5338
|
${nextSteps}`;
|
|
5349
5339
|
}
|
|
5350
5340
|
function searchCatalog(catalogDir, query) {
|
|
@@ -5373,7 +5363,7 @@ function searchCatalog(catalogDir, query) {
|
|
|
5373
5363
|
name: parsed.manifest.name,
|
|
5374
5364
|
score,
|
|
5375
5365
|
tokens: parsed.manifest.description_tokens,
|
|
5376
|
-
summary: parsed.manifest.description.length >
|
|
5366
|
+
summary: parsed.manifest.description.length > 30 ? `${parsed.manifest.description.slice(0, 27)}...` : parsed.manifest.description
|
|
5377
5367
|
});
|
|
5378
5368
|
}
|
|
5379
5369
|
}
|
|
@@ -5400,7 +5390,7 @@ function searchCatalog(catalogDir, query) {
|
|
|
5400
5390
|
name: parsed.manifest.name,
|
|
5401
5391
|
score,
|
|
5402
5392
|
tokens: parsed.manifest.system_prompt_tokens,
|
|
5403
|
-
summary: parsed.manifest.description.length >
|
|
5393
|
+
summary: parsed.manifest.description.length > 30 ? `${parsed.manifest.description.slice(0, 27)}...` : parsed.manifest.description
|
|
5404
5394
|
});
|
|
5405
5395
|
}
|
|
5406
5396
|
}
|
|
@@ -5430,43 +5420,39 @@ function formatCatalogSearchReport(report, format = "table", colorEnabled) {
|
|
|
5430
5420
|
return lines.join("\n");
|
|
5431
5421
|
}
|
|
5432
5422
|
const c = colorEnabled;
|
|
5433
|
-
const
|
|
5434
|
-
|
|
5435
|
-
`${style.bold(style.cyan("\u{1F50D} SkillOps Library Search", c), c)} \u2014 Query: ${style.bold(`"${report.query || "*"}"`, c)} (${report.total_matches} matches)`
|
|
5436
|
-
],
|
|
5437
|
-
{ minWidth: 74, colorEnabled: c }
|
|
5438
|
-
);
|
|
5423
|
+
const bar = style.dim("\u2502", c);
|
|
5424
|
+
const header = `${style.bold(style.cyan("\u25C6 SkillOps Library Search", c), c)} ${style.dim("\u2014", c)} Query: ${style.bold(`"${report.query || "*"}"`, c)} (${report.total_matches} matches)`;
|
|
5439
5425
|
if (report.matches.length === 0) {
|
|
5440
5426
|
return `${header}
|
|
5441
|
-
${formatBadge("warn", "No matching Skills or Subagents found.", c)}
|
|
5442
|
-
${renderNextSteps([{ command: "npx skillops-cli list", description: "View all 10 Skills & 9 Subagents
|
|
5427
|
+
${bar} ${formatBadge("warn", "No matching Skills or Subagents found.", c)}
|
|
5428
|
+
${renderNextSteps([{ command: "npx skillops-cli list", description: "View all 10 Skills & 9 Subagents" }], c)}`;
|
|
5443
5429
|
}
|
|
5444
5430
|
const table = renderTable(
|
|
5445
|
-
["Type", "Name", "Tokens", "
|
|
5431
|
+
["Type", "Name", "Tokens", "Summary"],
|
|
5446
5432
|
report.matches.map((m) => [
|
|
5447
5433
|
m.kind === "skill" ? formatBadge("skill", "SKILL", c) : formatBadge("subagent", "SUBAGENT", c),
|
|
5448
5434
|
style.bold(m.name, c),
|
|
5449
5435
|
`${m.tokens}t`,
|
|
5450
5436
|
m.summary
|
|
5451
5437
|
]),
|
|
5452
|
-
{ align: ["left", "left", "right", "left"], colorEnabled: c }
|
|
5438
|
+
{ align: ["left", "left", "right", "left"], colorEnabled: c, indent: 3 }
|
|
5453
5439
|
);
|
|
5454
5440
|
const topItem = report.matches[0]?.name ?? "bug-reproducer-tdd";
|
|
5455
5441
|
const nextSteps = renderNextSteps(
|
|
5456
5442
|
[
|
|
5457
5443
|
{
|
|
5458
5444
|
command: `npx skillops-cli info ${topItem}`,
|
|
5459
|
-
description:
|
|
5445
|
+
description: "Inspect triggers & usage"
|
|
5460
5446
|
},
|
|
5461
5447
|
{
|
|
5462
5448
|
command: `npx skillops-cli add ${topItem}`,
|
|
5463
|
-
description:
|
|
5449
|
+
description: "Install into AI agents"
|
|
5464
5450
|
}
|
|
5465
5451
|
],
|
|
5466
5452
|
c
|
|
5467
5453
|
);
|
|
5468
5454
|
return `${header}
|
|
5469
|
-
|
|
5455
|
+
${bar}
|
|
5470
5456
|
${table}
|
|
5471
5457
|
${nextSteps}`;
|
|
5472
5458
|
}
|
|
@@ -5684,38 +5670,31 @@ function formatScaffoldReport(result, format = "table", colorEnabled) {
|
|
|
5684
5670
|
].join("\n");
|
|
5685
5671
|
}
|
|
5686
5672
|
const c = colorEnabled;
|
|
5687
|
-
const
|
|
5688
|
-
|
|
5689
|
-
|
|
5690
|
-
|
|
5691
|
-
|
|
5692
|
-
|
|
5693
|
-
|
|
5694
|
-
{
|
|
5695
|
-
title: "\u{1F6E0}\uFE0F SkillOps Framework Scaffolder",
|
|
5696
|
-
borderColor: style.green,
|
|
5697
|
-
minWidth: 74,
|
|
5698
|
-
colorEnabled: c
|
|
5699
|
-
}
|
|
5700
|
-
);
|
|
5673
|
+
const bar = style.dim("\u2502", c);
|
|
5674
|
+
const treeHeader = [
|
|
5675
|
+
`${style.bold(style.cyan("\u25C6 SkillOps Framework Scaffolder", c), c)} ${style.dim("\u2014", c)} ${formatBadge("pass", "CREATED", c)} ${style.bold(result.kind.toUpperCase(), c)} ${style.bold(style.cyan(result.name, c), c)}`,
|
|
5676
|
+
bar,
|
|
5677
|
+
`${style.dim("\u251C\u2500", c)} ${style.bold("Generated Files:", c)}`,
|
|
5678
|
+
...result.created_files.map((f) => `${bar} \u2022 ${style.green(f, c)}`)
|
|
5679
|
+
].join("\n");
|
|
5701
5680
|
const nextSteps = renderNextSteps(
|
|
5702
5681
|
[
|
|
5703
5682
|
{
|
|
5704
5683
|
command: `npx skillops-cli info ${result.name}`,
|
|
5705
|
-
description: `Inspect
|
|
5684
|
+
description: `Inspect new ${result.kind} metadata & budget`
|
|
5706
5685
|
},
|
|
5707
5686
|
{
|
|
5708
5687
|
command: "npx skillops-cli audit --require-layout",
|
|
5709
|
-
description: "Verify INV-SKILL-01..04
|
|
5688
|
+
description: "Verify INV-SKILL-01..04 & collisions"
|
|
5710
5689
|
},
|
|
5711
5690
|
{
|
|
5712
5691
|
command: `npx skillops-cli add ${result.name}`,
|
|
5713
|
-
description: `
|
|
5692
|
+
description: `Install '${result.name}' into AI agents`
|
|
5714
5693
|
}
|
|
5715
5694
|
],
|
|
5716
5695
|
c
|
|
5717
5696
|
);
|
|
5718
|
-
return `${
|
|
5697
|
+
return `${treeHeader}
|
|
5719
5698
|
${nextSteps}`;
|
|
5720
5699
|
}
|
|
5721
5700
|
function runQuickstart(repoPath, catalogDir, options = {}) {
|
|
@@ -5814,34 +5793,35 @@ function formatQuickstartReport(report, format = "table", colorEnabled) {
|
|
|
5814
5793
|
].join("\n");
|
|
5815
5794
|
}
|
|
5816
5795
|
const c = colorEnabled;
|
|
5817
|
-
const
|
|
5818
|
-
const
|
|
5796
|
+
const bar = style.dim("\u2502", c);
|
|
5797
|
+
const stackLabel = [...report.detected_languages, ...report.detected_frameworks].join(", ") || "general";
|
|
5798
|
+
const targetsLabel = report.active_targets.length > 4 ? `${report.active_targets.slice(0, 4).join(", ")} (+${report.active_targets.length - 4})` : report.active_targets.join(", ");
|
|
5819
5799
|
const banner = renderHeaderBanner(
|
|
5820
|
-
`
|
|
5800
|
+
`Quickstart Setup ${report.dry_run ? "[DRY-RUN]" : "[READY]"}`,
|
|
5821
5801
|
{ colorEnabled: c }
|
|
5822
5802
|
);
|
|
5823
5803
|
const stepsBlock = [
|
|
5824
5804
|
renderStep(
|
|
5825
5805
|
1,
|
|
5826
5806
|
4,
|
|
5827
|
-
"Detect Stack &
|
|
5828
|
-
|
|
5807
|
+
"Detect Stack & Agents",
|
|
5808
|
+
`${style.cyan(stackLabel, c)} \xB7 ${style.bold(targetsLabel, c)}`,
|
|
5829
5809
|
"done",
|
|
5830
5810
|
c
|
|
5831
5811
|
),
|
|
5832
5812
|
renderStep(
|
|
5833
5813
|
2,
|
|
5834
5814
|
4,
|
|
5835
|
-
"Route
|
|
5836
|
-
`${style.green(`${report.selected_skills.length} Skills`, c)} + ${style.magenta(`${report.selected_subagents.length} Subagents`, c)}
|
|
5815
|
+
"Route Library Bundle",
|
|
5816
|
+
`${style.green(`${report.selected_skills.length} Skills`, c)} + ${style.magenta(`${report.selected_subagents.length} Subagents`, c)}`,
|
|
5837
5817
|
"done",
|
|
5838
5818
|
c
|
|
5839
5819
|
),
|
|
5840
5820
|
renderStep(
|
|
5841
5821
|
3,
|
|
5842
5822
|
4,
|
|
5843
|
-
"Transpile & Sync
|
|
5844
|
-
`${report.synced_files_count} files
|
|
5823
|
+
"Transpile & Sync",
|
|
5824
|
+
`${report.synced_files_count} files (${report.dry_run ? "dry-run" : ".skillops.yml + lockfile"})`,
|
|
5845
5825
|
"done",
|
|
5846
5826
|
c
|
|
5847
5827
|
),
|
|
@@ -5849,12 +5829,12 @@ function formatQuickstartReport(report, format = "table", colorEnabled) {
|
|
|
5849
5829
|
4,
|
|
5850
5830
|
4,
|
|
5851
5831
|
"Register MCP Server",
|
|
5852
|
-
`${report.mcp_configured_count} MCP
|
|
5832
|
+
`${report.mcp_configured_count} MCP agent config(s) wired`,
|
|
5853
5833
|
"done",
|
|
5854
5834
|
c
|
|
5855
5835
|
)
|
|
5856
5836
|
].join("\n");
|
|
5857
|
-
const tokenBar =
|
|
5837
|
+
const tokenBar = `${bar} ${renderTokenBar(
|
|
5858
5838
|
report.total_l1_tokens,
|
|
5859
5839
|
report.max_l1_budget,
|
|
5860
5840
|
{
|
|
@@ -5862,21 +5842,16 @@ function formatQuickstartReport(report, format = "table", colorEnabled) {
|
|
|
5862
5842
|
colorEnabled: c
|
|
5863
5843
|
}
|
|
5864
5844
|
)}`;
|
|
5865
|
-
const
|
|
5866
|
-
|
|
5867
|
-
|
|
5868
|
-
|
|
5869
|
-
""
|
|
5870
|
-
|
|
5871
|
-
|
|
5872
|
-
|
|
5873
|
-
{
|
|
5874
|
-
|
|
5875
|
-
borderColor: style.cyan,
|
|
5876
|
-
minWidth: 72,
|
|
5877
|
-
colorEnabled: c
|
|
5878
|
-
}
|
|
5879
|
-
);
|
|
5845
|
+
const bundleTree = [
|
|
5846
|
+
bar,
|
|
5847
|
+
`${style.dim("\u251C\u2500", c)} ${style.bold(style.cyan(`Active Bundle (${report.selected_skills.length} Skills \xB7 ${report.selected_subagents.length} Subagents)`, c), c)}`,
|
|
5848
|
+
`${bar} \u2022 ${style.bold("Skills:", c)} ${report.selected_skills.slice(0, 2).map((s) => style.cyan(s, c)).join(
|
|
5849
|
+
", "
|
|
5850
|
+
)}${report.selected_skills.length > 2 ? ` (+${report.selected_skills.length - 2} more)` : ""}`,
|
|
5851
|
+
`${bar} \u2022 ${style.bold("Subagents:", c)} ${report.selected_subagents.slice(0, 2).map((a) => style.magenta(a, c)).join(
|
|
5852
|
+
", "
|
|
5853
|
+
)}${report.selected_subagents.length > 2 ? ` (+${report.selected_subagents.length - 2} more)` : ""}`
|
|
5854
|
+
].join("\n");
|
|
5880
5855
|
const usageGuide = renderAiUsageGuide(
|
|
5881
5856
|
report.active_targets,
|
|
5882
5857
|
report.selected_skills,
|
|
@@ -5887,32 +5862,29 @@ function formatQuickstartReport(report, format = "table", colorEnabled) {
|
|
|
5887
5862
|
[
|
|
5888
5863
|
{
|
|
5889
5864
|
command: `npx skillops-cli info ${report.selected_skills[0] ?? "bug-reproducer-tdd"}`,
|
|
5890
|
-
description: "Inspect
|
|
5865
|
+
description: "Inspect Skill triggers & L3 scripts"
|
|
5891
5866
|
},
|
|
5892
5867
|
{
|
|
5893
5868
|
command: "npx skillops-cli list",
|
|
5894
|
-
description: "Browse all 10 Skills & 9 Subagents
|
|
5869
|
+
description: "Browse all 10 Skills & 9 Subagents"
|
|
5895
5870
|
},
|
|
5896
5871
|
{
|
|
5897
|
-
command: "npx skillops-cli create skill my-
|
|
5898
|
-
description: "Create
|
|
5872
|
+
command: "npx skillops-cli create skill my-skill",
|
|
5873
|
+
description: "Create a custom Skill"
|
|
5899
5874
|
},
|
|
5900
5875
|
{
|
|
5901
5876
|
command: "npx skillops-cli doctor",
|
|
5902
|
-
description: "Verify lockfile
|
|
5877
|
+
description: "Verify lockfile & Startup Token Tax"
|
|
5903
5878
|
}
|
|
5904
5879
|
],
|
|
5905
5880
|
c
|
|
5906
5881
|
);
|
|
5907
5882
|
return [
|
|
5908
5883
|
banner,
|
|
5909
|
-
|
|
5884
|
+
bar,
|
|
5910
5885
|
stepsBlock,
|
|
5911
|
-
"",
|
|
5912
5886
|
tokenBar,
|
|
5913
|
-
|
|
5914
|
-
bundleBox,
|
|
5915
|
-
"",
|
|
5887
|
+
bundleTree,
|
|
5916
5888
|
usageGuide,
|
|
5917
5889
|
nextSteps
|
|
5918
5890
|
].join("\n");
|
|
@@ -6026,15 +5998,18 @@ function runCli(argv) {
|
|
|
6026
5998
|
if (targetCmd && !targetCmd.startsWith("-")) {
|
|
6027
5999
|
const spec = findCommandHelpSpec(targetCmd);
|
|
6028
6000
|
if (spec) {
|
|
6029
|
-
process.stdout.write(renderCommandHelp(spec, SKILLOPS_VERSION)
|
|
6001
|
+
process.stdout.write(`${renderCommandHelp(spec, SKILLOPS_VERSION)}
|
|
6002
|
+
`);
|
|
6030
6003
|
return ExitCode.SUCCESS;
|
|
6031
6004
|
}
|
|
6032
6005
|
}
|
|
6033
|
-
process.stdout.write(renderGlobalHelp(SKILLOPS_VERSION)
|
|
6006
|
+
process.stdout.write(`${renderGlobalHelp(SKILLOPS_VERSION)}
|
|
6007
|
+
`);
|
|
6034
6008
|
return ExitCode.SUCCESS;
|
|
6035
6009
|
}
|
|
6036
6010
|
if (args.length === 0 || args[0] === "--help" || args[0] === "-h") {
|
|
6037
|
-
process.stdout.write(renderGlobalHelp(SKILLOPS_VERSION)
|
|
6011
|
+
process.stdout.write(`${renderGlobalHelp(SKILLOPS_VERSION)}
|
|
6012
|
+
`);
|
|
6038
6013
|
return ExitCode.SUCCESS;
|
|
6039
6014
|
}
|
|
6040
6015
|
if (args.includes("--help") || args.includes("-h")) {
|
|
@@ -6042,11 +6017,13 @@ function runCli(argv) {
|
|
|
6042
6017
|
if (firstCmd) {
|
|
6043
6018
|
const spec = findCommandHelpSpec(firstCmd);
|
|
6044
6019
|
if (spec) {
|
|
6045
|
-
process.stdout.write(renderCommandHelp(spec, SKILLOPS_VERSION)
|
|
6020
|
+
process.stdout.write(`${renderCommandHelp(spec, SKILLOPS_VERSION)}
|
|
6021
|
+
`);
|
|
6046
6022
|
return ExitCode.SUCCESS;
|
|
6047
6023
|
}
|
|
6048
6024
|
}
|
|
6049
|
-
process.stdout.write(renderGlobalHelp(SKILLOPS_VERSION)
|
|
6025
|
+
process.stdout.write(`${renderGlobalHelp(SKILLOPS_VERSION)}
|
|
6026
|
+
`);
|
|
6050
6027
|
return ExitCode.SUCCESS;
|
|
6051
6028
|
}
|
|
6052
6029
|
const command = args[0] ?? "";
|
|
@@ -6253,7 +6230,7 @@ function runCli(argv) {
|
|
|
6253
6230
|
return ExitCode.SUCCESS;
|
|
6254
6231
|
}
|
|
6255
6232
|
const l1Bar = renderProgressBar(summary.totalL1Tokens, 1500, {
|
|
6256
|
-
width:
|
|
6233
|
+
width: 10,
|
|
6257
6234
|
unit: "tokens"
|
|
6258
6235
|
});
|
|
6259
6236
|
const firstSkill = summary.skills[0]?.skillName ?? "security-sast-gate";
|
|
@@ -6271,15 +6248,15 @@ function runCli(argv) {
|
|
|
6271
6248
|
renderNextSteps([
|
|
6272
6249
|
{
|
|
6273
6250
|
command: `npx skillops-cli info ${firstSkill}`,
|
|
6274
|
-
description: "Inspect triggers
|
|
6251
|
+
description: "Inspect triggers & usage"
|
|
6275
6252
|
},
|
|
6276
6253
|
{
|
|
6277
6254
|
command: "npx skillops-cli search <keyword>",
|
|
6278
|
-
description: "Search Skills & Subagents
|
|
6255
|
+
description: "Search Skills & Subagents"
|
|
6279
6256
|
},
|
|
6280
6257
|
{
|
|
6281
6258
|
command: "npx skillops-cli quickstart",
|
|
6282
|
-
description: "Auto-detect
|
|
6259
|
+
description: "Auto-detect & install"
|
|
6283
6260
|
}
|
|
6284
6261
|
])
|
|
6285
6262
|
];
|