harnessed 3.4.1 → 3.4.3
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.mjs +257 -58
- package/dist/cli.mjs.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/workflows/auto/SKILL.md +9 -0
- package/workflows/capabilities.yaml +146 -71
- package/workflows/discuss/auto/SKILL.md +10 -2
- package/workflows/discuss/phase/SKILL.md +29 -6
- package/workflows/discuss/strategic/SKILL.md +32 -7
- package/workflows/discuss/subtask/SKILL.md +29 -6
- package/workflows/plan/architecture/SKILL.md +31 -6
- package/workflows/plan/auto/SKILL.md +10 -2
- package/workflows/plan/phase/SKILL.md +31 -6
- package/workflows/research/SKILL.md +31 -2
- package/workflows/retro/SKILL.md +29 -15
- package/workflows/role-prompts.yaml +477 -0
- package/workflows/task/auto/SKILL.md +10 -2
- package/workflows/task/clarify/SKILL.md +29 -21
- package/workflows/task/code/SKILL.md +31 -21
- package/workflows/task/deliver/SKILL.md +31 -21
- package/workflows/task/test/SKILL.md +31 -21
- package/workflows/verify/auto/SKILL.md +9 -1
- package/workflows/verify/code-review/SKILL.md +34 -16
- package/workflows/verify/design/SKILL.md +33 -15
- package/workflows/verify/multispec/SKILL.md +32 -16
- package/workflows/verify/paranoid/SKILL.md +36 -16
- package/workflows/verify/progress/SKILL.md +29 -15
- package/workflows/verify/qa/SKILL.md +32 -16
- package/workflows/verify/security/SKILL.md +34 -16
- package/workflows/verify/simplify/SKILL.md +32 -16
package/dist/cli.mjs
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { execSync, spawnSync, spawn } from 'child_process';
|
|
3
|
-
import { existsSync, mkdirSync, renameSync, writeFileSync, readFileSync,
|
|
3
|
+
import { existsSync, mkdirSync, renameSync, writeFileSync, readFileSync, readdirSync, appendFileSync } from 'fs';
|
|
4
4
|
import { join, resolve, dirname, relative } from 'path';
|
|
5
5
|
import { homedir } from 'os';
|
|
6
6
|
import { Type } from '@sinclair/typebox';
|
|
7
7
|
import { Value } from '@sinclair/typebox/value';
|
|
8
8
|
import { LineCounter, parseDocument, parse, isSeq, isScalar } from 'yaml';
|
|
9
|
-
import { readFile, readdir, unlink, writeFile, stat, rm, cp,
|
|
9
|
+
import { readFile, readdir, unlink, writeFile, stat, rm, cp, mkdir, access, rename } from 'fs/promises';
|
|
10
10
|
import lockfile from 'proper-lockfile';
|
|
11
11
|
import { Command } from 'commander';
|
|
12
12
|
import { Ajv } from 'ajv';
|
|
@@ -847,7 +847,7 @@ var init_resume = __esm({
|
|
|
847
847
|
|
|
848
848
|
// package.json
|
|
849
849
|
var package_default = {
|
|
850
|
-
version: "3.4.
|
|
850
|
+
version: "3.4.3"};
|
|
851
851
|
|
|
852
852
|
// src/manifest/errors.ts
|
|
853
853
|
function instancePathToKeyPath(instancePath) {
|
|
@@ -4854,6 +4854,109 @@ ${t("rollback.metadata_unreadable.fix")}`
|
|
|
4854
4854
|
console.log(t("rollback.restored", { count: meta.files.length, timestamp }));
|
|
4855
4855
|
});
|
|
4856
4856
|
}
|
|
4857
|
+
function readInstalledPlugins(homedirOverride) {
|
|
4858
|
+
const home = homedir();
|
|
4859
|
+
const path = join(home, ".claude", "plugins", "installed_plugins.json");
|
|
4860
|
+
let raw;
|
|
4861
|
+
try {
|
|
4862
|
+
raw = readFileSync(path, "utf8");
|
|
4863
|
+
} catch {
|
|
4864
|
+
return /* @__PURE__ */ new Set();
|
|
4865
|
+
}
|
|
4866
|
+
let parsed;
|
|
4867
|
+
try {
|
|
4868
|
+
parsed = JSON.parse(raw);
|
|
4869
|
+
} catch {
|
|
4870
|
+
return /* @__PURE__ */ new Set();
|
|
4871
|
+
}
|
|
4872
|
+
if (!parsed || typeof parsed !== "object") return /* @__PURE__ */ new Set();
|
|
4873
|
+
const plugins = parsed.plugins;
|
|
4874
|
+
if (!plugins || typeof plugins !== "object") return /* @__PURE__ */ new Set();
|
|
4875
|
+
const out = /* @__PURE__ */ new Set();
|
|
4876
|
+
for (const key of Object.keys(plugins)) {
|
|
4877
|
+
const at = key.indexOf("@");
|
|
4878
|
+
if (at <= 0) continue;
|
|
4879
|
+
out.add(key.slice(0, at));
|
|
4880
|
+
}
|
|
4881
|
+
return out;
|
|
4882
|
+
}
|
|
4883
|
+
function readInstalledUserSkills(homedirOverride) {
|
|
4884
|
+
const home = homedir();
|
|
4885
|
+
const skillsRoot = join(home, ".claude", "skills");
|
|
4886
|
+
try {
|
|
4887
|
+
const entries = readdirSync(skillsRoot, { withFileTypes: true });
|
|
4888
|
+
const out = /* @__PURE__ */ new Set();
|
|
4889
|
+
for (const e of entries) if (e.isDirectory()) out.add(e.name);
|
|
4890
|
+
return out;
|
|
4891
|
+
} catch {
|
|
4892
|
+
return /* @__PURE__ */ new Set();
|
|
4893
|
+
}
|
|
4894
|
+
}
|
|
4895
|
+
function resolveCapabilityCmd(capability, installedPlugins, installedUserSkills) {
|
|
4896
|
+
const { cmd, install_type, plugin_id, skill_dir } = capability;
|
|
4897
|
+
if (!install_type) return { renderedCmd: cmd };
|
|
4898
|
+
const types = Array.isArray(install_type) ? install_type : [install_type];
|
|
4899
|
+
const uniqueTypes = [...new Set(types)];
|
|
4900
|
+
const missingHints = [];
|
|
4901
|
+
let anyDetected = false;
|
|
4902
|
+
for (const t2 of uniqueTypes) {
|
|
4903
|
+
if (t2 === "plugin") {
|
|
4904
|
+
if (!plugin_id) {
|
|
4905
|
+
missingHints.push(
|
|
4906
|
+
`install_type=plugin declared but no plugin_id (capabilities.yaml schema bug)`
|
|
4907
|
+
);
|
|
4908
|
+
continue;
|
|
4909
|
+
}
|
|
4910
|
+
if (installedPlugins.has(plugin_id)) {
|
|
4911
|
+
anyDetected = true;
|
|
4912
|
+
break;
|
|
4913
|
+
}
|
|
4914
|
+
missingHints.push(`plugin '${plugin_id}' (\`claude plugin install ${plugin_id}\`)`);
|
|
4915
|
+
} else {
|
|
4916
|
+
if (!skill_dir) {
|
|
4917
|
+
missingHints.push(
|
|
4918
|
+
`install_type=user-skill declared but no skill_dir (capabilities.yaml schema bug)`
|
|
4919
|
+
);
|
|
4920
|
+
continue;
|
|
4921
|
+
}
|
|
4922
|
+
if (installedUserSkills.has(skill_dir)) {
|
|
4923
|
+
anyDetected = true;
|
|
4924
|
+
break;
|
|
4925
|
+
}
|
|
4926
|
+
missingHints.push(
|
|
4927
|
+
`user-skill '${skill_dir}' under ~/.claude/skills/ (git clone the official repo; e.g. gstack: \`git clone https://github.com/garrytan/gstack.git ~/.claude/skills/gstack && cd ~/.claude/skills/gstack && ./setup\`)`
|
|
4928
|
+
);
|
|
4929
|
+
}
|
|
4930
|
+
}
|
|
4931
|
+
if (anyDetected) return { renderedCmd: cmd };
|
|
4932
|
+
const prefix = uniqueTypes.length > 1 ? "[multi]" : `[${uniqueTypes[0]}]`;
|
|
4933
|
+
const joined = missingHints.join(" OR ");
|
|
4934
|
+
return {
|
|
4935
|
+
renderedCmd: cmd,
|
|
4936
|
+
warning: `${prefix} '${cmd}' backing missing \u2014 install either: ${joined}.`
|
|
4937
|
+
};
|
|
4938
|
+
}
|
|
4939
|
+
var CAPABILITY_CMD_TEMPLATE = /\{\{\s*capabilities\.([a-zA-Z0-9_-]+)\.cmd\s*\}\}/g;
|
|
4940
|
+
function renderSkillBody(body, capabilities, installedPlugins, installedUserSkills) {
|
|
4941
|
+
const warningsSet = /* @__PURE__ */ new Set();
|
|
4942
|
+
const out = body.replace(CAPABILITY_CMD_TEMPLATE, (match2, name) => {
|
|
4943
|
+
const cap = capabilities[name];
|
|
4944
|
+
if (!cap) {
|
|
4945
|
+
warningsSet.add(
|
|
4946
|
+
`capability '${name}' referenced in SKILL.md but not defined in capabilities.yaml`
|
|
4947
|
+
);
|
|
4948
|
+
return match2;
|
|
4949
|
+
}
|
|
4950
|
+
const { renderedCmd, warning } = resolveCapabilityCmd(
|
|
4951
|
+
cap,
|
|
4952
|
+
installedPlugins,
|
|
4953
|
+
installedUserSkills
|
|
4954
|
+
);
|
|
4955
|
+
if (warning) warningsSet.add(warning);
|
|
4956
|
+
return renderedCmd;
|
|
4957
|
+
});
|
|
4958
|
+
return { body: out, warnings: [...warningsSet] };
|
|
4959
|
+
}
|
|
4857
4960
|
|
|
4858
4961
|
// src/cli/lib/enableAgentTeamsInSettings.ts
|
|
4859
4962
|
init_harnessedRoot();
|
|
@@ -5020,72 +5123,121 @@ async function atomicWrite2(path, content) {
|
|
|
5020
5123
|
return `write ${path} failed: ${err2.message}`;
|
|
5021
5124
|
}
|
|
5022
5125
|
}
|
|
5023
|
-
function
|
|
5024
|
-
const
|
|
5025
|
-
const path = join(home, ".claude", "plugins", "installed_plugins.json");
|
|
5126
|
+
async function loadRolePrompts(workflowsDir) {
|
|
5127
|
+
const path = join(workflowsDir, "role-prompts.yaml");
|
|
5026
5128
|
let raw;
|
|
5027
5129
|
try {
|
|
5028
|
-
raw =
|
|
5029
|
-
} catch {
|
|
5030
|
-
return /* @__PURE__ */ new Set();
|
|
5031
|
-
}
|
|
5032
|
-
let parsed;
|
|
5033
|
-
try {
|
|
5034
|
-
parsed = JSON.parse(raw);
|
|
5130
|
+
raw = await readFile(path, "utf8");
|
|
5035
5131
|
} catch {
|
|
5036
|
-
return
|
|
5037
|
-
}
|
|
5038
|
-
if (!parsed || typeof parsed !== "object") return /* @__PURE__ */ new Set();
|
|
5039
|
-
const plugins = parsed.plugins;
|
|
5040
|
-
if (!plugins || typeof plugins !== "object") return /* @__PURE__ */ new Set();
|
|
5041
|
-
const out = /* @__PURE__ */ new Set();
|
|
5042
|
-
for (const key of Object.keys(plugins)) {
|
|
5043
|
-
const at = key.indexOf("@");
|
|
5044
|
-
if (at <= 0) continue;
|
|
5045
|
-
out.add(key.slice(0, at));
|
|
5046
|
-
}
|
|
5047
|
-
return out;
|
|
5048
|
-
}
|
|
5049
|
-
function resolveCapabilityCmd(capability, installedPlugins) {
|
|
5050
|
-
const { cmd, plugin_namespace } = capability;
|
|
5051
|
-
if (!plugin_namespace) return { renderedCmd: cmd };
|
|
5052
|
-
if (cmd.includes(":")) return { renderedCmd: cmd };
|
|
5053
|
-
if (!cmd.startsWith("/")) return { renderedCmd: cmd };
|
|
5054
|
-
if (!installedPlugins.has(plugin_namespace)) {
|
|
5055
|
-
return {
|
|
5056
|
-
renderedCmd: cmd,
|
|
5057
|
-
warning: `plugin '${plugin_namespace}' not installed \u2014 '${cmd}' will not resolve via Claude Code. install: 'claude plugin install ${plugin_namespace}' or see plugin docs.`
|
|
5058
|
-
};
|
|
5132
|
+
return {};
|
|
5059
5133
|
}
|
|
5060
|
-
const
|
|
5061
|
-
return
|
|
5134
|
+
const doc = parse(raw);
|
|
5135
|
+
return doc?.prompts ?? {};
|
|
5136
|
+
}
|
|
5137
|
+
function generateCommandFile(name, prompt, capabilities, installedPlugins, installedUserSkills) {
|
|
5138
|
+
const isMaster = prompt.is_master === true;
|
|
5139
|
+
const primaryCmdLine = prompt.primary_cap && capabilities[prompt.primary_cap] ? `{{ capabilities.${prompt.primary_cap}.cmd }}` : "";
|
|
5140
|
+
const checklistBlock = prompt.checklist.length ? prompt.checklist.map((item, i) => `> ${i + 1}. ${item}`).join("\n>\n") : "> (Master orchestrator \u2014 dispatches to per-sub-workflow slash commands listed below.)";
|
|
5141
|
+
const fallbackPath = isMaster ? `**Fallback path** (when no slash command from the sub-list resolves): run each missing sub-workflow inline using its own role prompt (see \`~/.claude/skills/<sub-name>/SKILL.md\` for the per-sub fallback prompt). Do NOT skip stages silently \u2014 each sub either runs or is logged as "skipped: <reason>".` : [
|
|
5142
|
+
`**Fallback path** (when the upstream isn't installed or returns no result): use the Task tool to spawn a general-purpose subagent with this prompt:`,
|
|
5143
|
+
``,
|
|
5144
|
+
`> You are a **${prompt.specialist}**.`,
|
|
5145
|
+
`>`,
|
|
5146
|
+
`> **Mission**: ${prompt.responsibility.trim().replace(/\n/g, " ")}`,
|
|
5147
|
+
`>`,
|
|
5148
|
+
`> **Default-suspect mode**: assume the change is broken / risky / incomplete until proven otherwise. Cite \`file:line\` for every finding; do not generalize.`,
|
|
5149
|
+
`>`,
|
|
5150
|
+
`> **Review checklist**:`,
|
|
5151
|
+
checklistBlock,
|
|
5152
|
+
`>`,
|
|
5153
|
+
`> **Output format**: structured report with severity-classified findings (${prompt.severity}). One finding per line: \`[severity] file:line \u2014 problem (one sentence); fix: suggested change\`. If no findings, say so explicitly. No preamble, no end-of-report summary.`,
|
|
5154
|
+
``,
|
|
5155
|
+
`(The role prompt is self-contained \u2014 works even when the upstream \`${prompt.primary_cap || "specialist"}\` user-skill / plugin isn't installed.)`
|
|
5156
|
+
].join("\n");
|
|
5157
|
+
const preferredPath = primaryCmdLine ? `**Preferred path** (when the upstream specialist is installed): use the SlashCommand tool to run \`${primaryCmdLine}\` \u2014 the upstream specialist takes over.` : `**Preferred path** (master orchestrator): dispatch to the per-sub-workflow slash commands in the order this stage prescribes. Each sub command is its own \`~/.claude/commands/<sub-name>.md\` and has its own dual-path fallback.`;
|
|
5158
|
+
const rawBody = [
|
|
5159
|
+
`# /${name}`,
|
|
5160
|
+
``,
|
|
5161
|
+
prompt.description,
|
|
5162
|
+
``,
|
|
5163
|
+
`## How to invoke`,
|
|
5164
|
+
``,
|
|
5165
|
+
preferredPath,
|
|
5166
|
+
``,
|
|
5167
|
+
fallbackPath,
|
|
5168
|
+
``,
|
|
5169
|
+
`## Notes`,
|
|
5170
|
+
``,
|
|
5171
|
+
`- This file (\`~/.claude/commands/${name}.md\`) is generated by \`harnessed setup\` from \`workflows/role-prompts.yaml\` + \`workflows/<stage>/<sub>/SKILL.md\`. To regenerate after a harnessed upgrade, re-run \`harnessed setup\`.`,
|
|
5172
|
+
`- The companion \`~/.claude/skills/${name}/SKILL.md\` is the Skill-tool entry point (Claude loads it when triggers match \`trigger_phrases:\`). Both files carry the same dual-path instruction.`,
|
|
5173
|
+
`- If your shell shows a \`\u26A0\uFE0F ... not installed\` warning from \`harnessed setup\` for this command, the upstream is missing on disk \u2014 install per the warning, OR rely on the fallback Task-spawn role prompt above (it does not require the upstream).`,
|
|
5174
|
+
``
|
|
5175
|
+
].join("\n");
|
|
5176
|
+
const { body, warnings } = renderSkillBody(
|
|
5177
|
+
rawBody,
|
|
5178
|
+
capabilities,
|
|
5179
|
+
installedPlugins,
|
|
5180
|
+
installedUserSkills
|
|
5181
|
+
);
|
|
5182
|
+
const frontmatter = ["---", `description: ${JSON.stringify(prompt.description)}`, "---", ""].join(
|
|
5183
|
+
"\n"
|
|
5184
|
+
);
|
|
5185
|
+
return { content: frontmatter + body, warnings };
|
|
5062
5186
|
}
|
|
5063
|
-
|
|
5064
|
-
|
|
5065
|
-
const
|
|
5066
|
-
const
|
|
5067
|
-
const
|
|
5068
|
-
|
|
5069
|
-
|
|
5070
|
-
|
|
5071
|
-
|
|
5072
|
-
|
|
5187
|
+
async function writeAllCommands(slashNames, commandsDir, rolePrompts, capabilities, installedPlugins, installedUserSkills, writer, fileExists = existsSync) {
|
|
5188
|
+
const results = [];
|
|
5189
|
+
const aggregatedWarnings = /* @__PURE__ */ new Set();
|
|
5190
|
+
for (const name of slashNames) {
|
|
5191
|
+
const path = join(commandsDir, `${name}.md`);
|
|
5192
|
+
const prompt = rolePrompts[name];
|
|
5193
|
+
if (!prompt) {
|
|
5194
|
+
results.push({
|
|
5195
|
+
name,
|
|
5196
|
+
path,
|
|
5197
|
+
written: false,
|
|
5198
|
+
warning: `no role-prompts.yaml entry for '${name}' \u2014 skipping commands/${name}.md generation`
|
|
5199
|
+
});
|
|
5200
|
+
aggregatedWarnings.add(`role-prompts.yaml missing entry for '${name}'`);
|
|
5201
|
+
continue;
|
|
5073
5202
|
}
|
|
5074
|
-
|
|
5075
|
-
|
|
5076
|
-
|
|
5077
|
-
|
|
5078
|
-
|
|
5203
|
+
if (fileExists(path)) {
|
|
5204
|
+
results.push({
|
|
5205
|
+
name,
|
|
5206
|
+
path,
|
|
5207
|
+
written: false,
|
|
5208
|
+
warning: `commands/${name}.md already exists \u2014 leaving user file unchanged`
|
|
5209
|
+
});
|
|
5210
|
+
continue;
|
|
5211
|
+
}
|
|
5212
|
+
const { content, warnings } = generateCommandFile(
|
|
5213
|
+
name,
|
|
5214
|
+
prompt,
|
|
5215
|
+
capabilities,
|
|
5216
|
+
installedPlugins,
|
|
5217
|
+
installedUserSkills
|
|
5218
|
+
);
|
|
5219
|
+
try {
|
|
5220
|
+
await writer(path, content);
|
|
5221
|
+
results.push({ name, path, written: true });
|
|
5222
|
+
} catch (e) {
|
|
5223
|
+
results.push({
|
|
5224
|
+
name,
|
|
5225
|
+
path,
|
|
5226
|
+
written: false,
|
|
5227
|
+
warning: `write failed for commands/${name}.md: ${e.message}`
|
|
5228
|
+
});
|
|
5229
|
+
}
|
|
5230
|
+
for (const w of warnings) aggregatedWarnings.add(w);
|
|
5231
|
+
}
|
|
5232
|
+
return { results, warnings: [...aggregatedWarnings] };
|
|
5079
5233
|
}
|
|
5080
|
-
|
|
5081
|
-
// src/cli/lib/renderSkillTemplates.ts
|
|
5082
5234
|
async function loadCapabilities(workflowsDir) {
|
|
5083
5235
|
const path = join(workflowsDir, "capabilities.yaml");
|
|
5084
5236
|
const raw = await readFile(path, "utf8");
|
|
5085
5237
|
const doc = parse(raw);
|
|
5086
5238
|
return doc?.capabilities ?? {};
|
|
5087
5239
|
}
|
|
5088
|
-
async function renderSkillFile(skillName, skillsBase, capabilities, installedPlugins) {
|
|
5240
|
+
async function renderSkillFile(skillName, skillsBase, capabilities, installedPlugins, installedUserSkills) {
|
|
5089
5241
|
const skillPath = join(skillsBase, skillName, "SKILL.md");
|
|
5090
5242
|
const result = {
|
|
5091
5243
|
name: skillName,
|
|
@@ -5100,7 +5252,7 @@ async function renderSkillFile(skillName, skillsBase, capabilities, installedPlu
|
|
|
5100
5252
|
result.error = `read failed: ${e.message}`;
|
|
5101
5253
|
return result;
|
|
5102
5254
|
}
|
|
5103
|
-
const rendered = renderSkillBody(body, capabilities, installedPlugins);
|
|
5255
|
+
const rendered = renderSkillBody(body, capabilities, installedPlugins, installedUserSkills);
|
|
5104
5256
|
if (rendered.body === body) {
|
|
5105
5257
|
result.warnings = rendered.warnings;
|
|
5106
5258
|
return result;
|
|
@@ -5133,10 +5285,17 @@ async function renderAllSkills(skillNames, skillsBase, workflowsDir, homedirOver
|
|
|
5133
5285
|
};
|
|
5134
5286
|
}
|
|
5135
5287
|
const installedPlugins = readInstalledPlugins();
|
|
5288
|
+
const installedUserSkills = readInstalledUserSkills();
|
|
5136
5289
|
const results = [];
|
|
5137
5290
|
const warningSet = /* @__PURE__ */ new Set();
|
|
5138
5291
|
for (const name of skillNames) {
|
|
5139
|
-
const r = await renderSkillFile(
|
|
5292
|
+
const r = await renderSkillFile(
|
|
5293
|
+
name,
|
|
5294
|
+
skillsBase,
|
|
5295
|
+
capabilities,
|
|
5296
|
+
installedPlugins,
|
|
5297
|
+
installedUserSkills
|
|
5298
|
+
);
|
|
5140
5299
|
results.push(r);
|
|
5141
5300
|
for (const w of r.warnings) warningSet.add(w);
|
|
5142
5301
|
if (r.error) warningSet.add(`${name}: ${r.error}`);
|
|
@@ -5378,6 +5537,46 @@ function registerSetup(program2) {
|
|
|
5378
5537
|
console.warn(` - ${w}`);
|
|
5379
5538
|
}
|
|
5380
5539
|
}
|
|
5540
|
+
const commandsBase = resolve(homedir(), ".claude", "commands");
|
|
5541
|
+
try {
|
|
5542
|
+
await mkdir(commandsBase, { recursive: true });
|
|
5543
|
+
} catch (e) {
|
|
5544
|
+
console.warn(
|
|
5545
|
+
` [A.6] could not create ${commandsBase} \u2014 skipping commands/ generation (${e.message})`
|
|
5546
|
+
);
|
|
5547
|
+
}
|
|
5548
|
+
let capabilitiesMap = {};
|
|
5549
|
+
try {
|
|
5550
|
+
capabilitiesMap = await loadCapabilities(workflowsDir);
|
|
5551
|
+
} catch (e) {
|
|
5552
|
+
console.warn(
|
|
5553
|
+
` [A.6] capabilities.yaml unreadable \u2014 skipping commands/ generation (${e.message})`
|
|
5554
|
+
);
|
|
5555
|
+
}
|
|
5556
|
+
const rolePrompts = await loadRolePrompts(workflowsDir);
|
|
5557
|
+
const installedPlugins = readInstalledPlugins();
|
|
5558
|
+
const installedUserSkills = readInstalledUserSkills();
|
|
5559
|
+
const cmdResult = await writeAllCommands(
|
|
5560
|
+
skillNames,
|
|
5561
|
+
commandsBase,
|
|
5562
|
+
rolePrompts,
|
|
5563
|
+
capabilitiesMap,
|
|
5564
|
+
installedPlugins,
|
|
5565
|
+
installedUserSkills,
|
|
5566
|
+
async (p4, c) => writeFile(p4, c, "utf8")
|
|
5567
|
+
);
|
|
5568
|
+
const writtenCount = cmdResult.results.filter((r) => r.written).length;
|
|
5569
|
+
const skippedCount = cmdResult.results.filter((r) => !r.written && r.warning).length;
|
|
5570
|
+
console.log(
|
|
5571
|
+
` [A.6] generated ${writtenCount} commands/<x>.md file(s) (${skippedCount} skipped \u2014 existing user file or schema warn)`
|
|
5572
|
+
);
|
|
5573
|
+
for (const r of cmdResult.results) {
|
|
5574
|
+
if (r.written) {
|
|
5575
|
+
console.log(` [A.6] wrote /${r.name} \u2192 ${r.path}`);
|
|
5576
|
+
} else if (r.warning) {
|
|
5577
|
+
console.warn(` [A.6] skipped /${r.name}: ${r.warning}`);
|
|
5578
|
+
}
|
|
5579
|
+
}
|
|
5381
5580
|
const cResult = await enableAgentTeamsInSettings();
|
|
5382
5581
|
if (cResult.status === "created") {
|
|
5383
5582
|
console.log(t("setup.step_c.created", { path: cResult.path }));
|