@chllming/wave-orchestration 0.5.3 → 0.5.4
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/CHANGELOG.md +7 -0
- package/README.md +56 -509
- package/docs/README.md +39 -0
- package/docs/concepts/context7-vs-skills.md +94 -0
- package/docs/concepts/operating-modes.md +91 -0
- package/docs/concepts/runtime-agnostic-orchestration.md +95 -0
- package/docs/concepts/what-is-a-wave.md +133 -0
- package/docs/guides/planner.md +113 -0
- package/docs/guides/terminal-surfaces.md +80 -0
- package/docs/image.png +0 -0
- package/docs/plans/context7-wave-orchestrator.md +2 -0
- package/docs/plans/current-state.md +10 -0
- package/docs/plans/master-plan.md +3 -3
- package/docs/plans/migration.md +4 -3
- package/docs/plans/wave-orchestrator.md +27 -3
- package/docs/reference/runtime-config/README.md +19 -0
- package/docs/reference/skills.md +156 -0
- package/docs/roadmap.md +160 -564
- package/package.json +2 -1
- package/releases/manifest.json +17 -0
- package/scripts/wave-orchestrator/config.mjs +17 -0
- package/scripts/wave-orchestrator/context7.mjs +9 -0
- package/scripts/wave-orchestrator/coordination.mjs +16 -0
- package/scripts/wave-orchestrator/executors.mjs +24 -11
- package/scripts/wave-orchestrator/install.mjs +41 -2
- package/scripts/wave-orchestrator/launcher.mjs +113 -20
- package/scripts/wave-orchestrator/planner.mjs +1328 -0
- package/scripts/wave-orchestrator/project-profile.mjs +190 -0
- package/scripts/wave-orchestrator/shared.mjs +2 -0
- package/scripts/wave-orchestrator/skills.mjs +448 -0
- package/scripts/wave-orchestrator/terminals.mjs +16 -0
- package/scripts/wave-orchestrator/traces.mjs +23 -0
- package/scripts/wave-orchestrator/wave-files.mjs +299 -84
- package/scripts/wave.mjs +11 -0
- package/skills/provider-aws/SKILL.md +6 -0
- package/skills/provider-aws/skill.json +5 -0
- package/skills/provider-custom-deploy/SKILL.md +5 -0
- package/skills/provider-custom-deploy/skill.json +5 -0
- package/skills/provider-docker-compose/SKILL.md +6 -0
- package/skills/provider-docker-compose/skill.json +5 -0
- package/skills/provider-github-release/SKILL.md +6 -0
- package/skills/provider-github-release/skill.json +5 -0
- package/skills/provider-kubernetes/SKILL.md +6 -0
- package/skills/provider-kubernetes/skill.json +5 -0
- package/skills/provider-railway/SKILL.md +6 -0
- package/skills/provider-railway/adapters/claude.md +1 -0
- package/skills/provider-railway/adapters/codex.md +1 -0
- package/skills/provider-railway/adapters/local.md +1 -0
- package/skills/provider-railway/adapters/opencode.md +1 -0
- package/skills/provider-railway/skill.json +5 -0
- package/skills/provider-ssh-manual/SKILL.md +6 -0
- package/skills/provider-ssh-manual/skill.json +5 -0
- package/skills/repo-coding-rules/SKILL.md +7 -0
- package/skills/repo-coding-rules/skill.json +5 -0
- package/skills/role-deploy/SKILL.md +6 -0
- package/skills/role-deploy/skill.json +5 -0
- package/skills/role-documentation/SKILL.md +6 -0
- package/skills/role-documentation/skill.json +5 -0
- package/skills/role-evaluator/SKILL.md +6 -0
- package/skills/role-evaluator/skill.json +5 -0
- package/skills/role-implementation/SKILL.md +6 -0
- package/skills/role-implementation/skill.json +5 -0
- package/skills/role-infra/SKILL.md +6 -0
- package/skills/role-infra/skill.json +5 -0
- package/skills/role-integration/SKILL.md +6 -0
- package/skills/role-integration/skill.json +5 -0
- package/skills/role-research/SKILL.md +6 -0
- package/skills/role-research/skill.json +5 -0
- package/skills/runtime-claude/SKILL.md +6 -0
- package/skills/runtime-claude/skill.json +5 -0
- package/skills/runtime-codex/SKILL.md +6 -0
- package/skills/runtime-codex/skill.json +5 -0
- package/skills/runtime-local/SKILL.md +5 -0
- package/skills/runtime-local/skill.json +5 -0
- package/skills/runtime-opencode/SKILL.md +6 -0
- package/skills/runtime-opencode/skill.json +5 -0
- package/skills/wave-core/SKILL.md +7 -0
- package/skills/wave-core/skill.json +5 -0
- package/wave.config.json +27 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chllming/wave-orchestration",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.4",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Generic wave-based multi-agent orchestration for repository work.",
|
|
6
6
|
"repository": {
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
},
|
|
17
17
|
"files": [
|
|
18
18
|
"scripts",
|
|
19
|
+
"skills",
|
|
19
20
|
"docs",
|
|
20
21
|
"releases",
|
|
21
22
|
"wave.config.json",
|
package/releases/manifest.json
CHANGED
|
@@ -2,6 +2,23 @@
|
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"packageName": "@chllming/wave-orchestration",
|
|
4
4
|
"releases": [
|
|
5
|
+
{
|
|
6
|
+
"version": "0.5.4",
|
|
7
|
+
"date": "2026-03-22",
|
|
8
|
+
"summary": "Planner foundation, cross-runtime skills, and clearer docs and reconcile output.",
|
|
9
|
+
"features": [
|
|
10
|
+
"The planner foundation now ships with `.wave/project-profile.json`, `wave project setup|show`, and `wave draft`, which writes both structured JSON specs and launcher-compatible wave markdown.",
|
|
11
|
+
"Canonical repo-owned skill bundles now live under `skills/`, with attachment by base, role, runtime, deploy kind, and explicit per-agent `### Skills`, then projection into Codex, Claude Code, OpenCode, and local executor overlays.",
|
|
12
|
+
"The docs surface now includes a docs index plus focused concept, guide, and reference pages for waves, planner workflow, operating modes, Context7 vs skills, terminal surfaces, and runtime-agnostic orchestration.",
|
|
13
|
+
"Reconcile output now explains why incomplete waves cannot be reconstructed, making `wave launch --reconcile-status` failures easier to interpret."
|
|
14
|
+
],
|
|
15
|
+
"manualSteps": [
|
|
16
|
+
"After upgrading, run `pnpm exec wave project setup` once so the repo has an explicit project profile with default lane, oversight mode, terminal surface, and deploy-environment memory.",
|
|
17
|
+
"Review `wave.config.json` `skills` mappings and the seeded `skills/` bundles before relying on runtime-specific or deploy-specific skill attachment.",
|
|
18
|
+
"Dry-run at least one generated or existing wave with `pnpm exec wave launch --lane main --dry-run --no-dashboard` to inspect the new skill overlay artifacts and launch previews."
|
|
19
|
+
],
|
|
20
|
+
"breaking": false
|
|
21
|
+
},
|
|
5
22
|
{
|
|
6
23
|
"version": "0.5.3",
|
|
7
24
|
"date": "2026-03-22",
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { WORKSPACE_ROOT } from "./roots.mjs";
|
|
4
|
+
import {
|
|
5
|
+
emptySkillsConfig,
|
|
6
|
+
mergeSkillsConfig,
|
|
7
|
+
normalizeSkillsConfig,
|
|
8
|
+
} from "./skills.mjs";
|
|
4
9
|
|
|
5
10
|
const REPO_ROOT = WORKSPACE_ROOT;
|
|
6
11
|
|
|
@@ -388,6 +393,10 @@ function normalizeRuntimePolicy(rawRuntimePolicy = {}) {
|
|
|
388
393
|
};
|
|
389
394
|
}
|
|
390
395
|
|
|
396
|
+
function normalizeLaneSkills(rawSkills = {}, lane = "skills", options = {}) {
|
|
397
|
+
return normalizeSkillsConfig(rawSkills, lane, options);
|
|
398
|
+
}
|
|
399
|
+
|
|
391
400
|
function normalizeClaudePromptMode(value, label = "executors.claude.appendSystemPromptMode") {
|
|
392
401
|
const normalized = String(value || "append")
|
|
393
402
|
.trim()
|
|
@@ -751,6 +760,7 @@ export function loadWaveConfig(configPath = DEFAULT_WAVE_CONFIG_PATH) {
|
|
|
751
760
|
roles: normalizeRoles(rawConfig.roles),
|
|
752
761
|
validation: normalizeValidation(rawConfig.validation),
|
|
753
762
|
executors: normalizeExecutors(rawConfig.executors),
|
|
763
|
+
skills: normalizeLaneSkills(rawConfig.skills, "skills"),
|
|
754
764
|
capabilityRouting: normalizeCapabilityRouting(rawConfig.capabilityRouting),
|
|
755
765
|
runtimePolicy: normalizeRuntimePolicy(rawConfig.runtimePolicy),
|
|
756
766
|
sharedPlanDocs,
|
|
@@ -785,6 +795,12 @@ export function resolveLaneProfile(config, laneInput = config.defaultLane) {
|
|
|
785
795
|
const executors = normalizeExecutors(
|
|
786
796
|
mergeExecutors(config.executors, laneConfig.executors),
|
|
787
797
|
);
|
|
798
|
+
const skills = mergeSkillsConfig(
|
|
799
|
+
config.skills || emptySkillsConfig(),
|
|
800
|
+
normalizeLaneSkills(laneConfig.skills, `${lane}.skills`, {
|
|
801
|
+
preserveOmittedDir: true,
|
|
802
|
+
}),
|
|
803
|
+
);
|
|
788
804
|
const capabilityRouting = normalizeCapabilityRouting({
|
|
789
805
|
...config.capabilityRouting,
|
|
790
806
|
...(laneConfig.capabilityRouting || {}),
|
|
@@ -812,6 +828,7 @@ export function resolveLaneProfile(config, laneInput = config.defaultLane) {
|
|
|
812
828
|
roles,
|
|
813
829
|
validation,
|
|
814
830
|
executors,
|
|
831
|
+
skills,
|
|
815
832
|
capabilityRouting,
|
|
816
833
|
runtimePolicy,
|
|
817
834
|
paths: {
|
|
@@ -221,6 +221,15 @@ export function buildAgentPromptFingerprintSource(agent) {
|
|
|
221
221
|
components: agent?.components || [],
|
|
222
222
|
componentTargets: agent?.componentTargets || null,
|
|
223
223
|
executorResolved: agent?.executorResolved || null,
|
|
224
|
+
skillsResolved: agent?.skillsResolved
|
|
225
|
+
? {
|
|
226
|
+
ids: agent.skillsResolved.ids || [],
|
|
227
|
+
role: agent.skillsResolved.role || null,
|
|
228
|
+
runtime: agent.skillsResolved.runtime || null,
|
|
229
|
+
deployKind: agent.skillsResolved.deployKind || null,
|
|
230
|
+
promptHash: agent.skillsResolved.promptHash || null,
|
|
231
|
+
}
|
|
232
|
+
: null,
|
|
224
233
|
});
|
|
225
234
|
}
|
|
226
235
|
|
|
@@ -349,6 +349,21 @@ export function buildExecutionPrompt({
|
|
|
349
349
|
"",
|
|
350
350
|
]
|
|
351
351
|
: [];
|
|
352
|
+
const skillLines =
|
|
353
|
+
Array.isArray(agent.skillsResolved?.ids) && agent.skillsResolved.ids.length > 0
|
|
354
|
+
? [
|
|
355
|
+
"Active skill packs for this run:",
|
|
356
|
+
...agent.skillsResolved.ids.map((skillId) => `- ${skillId}`),
|
|
357
|
+
"- Treat the following skill payload as additive guidance. Repository source, standing role prompts, and ownership boundaries remain authoritative.",
|
|
358
|
+
"",
|
|
359
|
+
"## Skill context",
|
|
360
|
+
"",
|
|
361
|
+
"```text",
|
|
362
|
+
agent.skillsResolved.promptText || "",
|
|
363
|
+
"```",
|
|
364
|
+
"",
|
|
365
|
+
]
|
|
366
|
+
: [];
|
|
352
367
|
|
|
353
368
|
return [
|
|
354
369
|
`Working directory: ${REPO_ROOT}`,
|
|
@@ -413,6 +428,7 @@ export function buildExecutionPrompt({
|
|
|
413
428
|
...promotedComponentLines,
|
|
414
429
|
...ownedComponentLines,
|
|
415
430
|
...deliverableLines,
|
|
431
|
+
...skillLines,
|
|
416
432
|
...context7PromptLines,
|
|
417
433
|
"Assigned implementation prompt:",
|
|
418
434
|
"```",
|
|
@@ -134,7 +134,7 @@ function buildClaudeSettingsPath(executor, overlayDir) {
|
|
|
134
134
|
return settingsPath;
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
-
function buildOpenCodeConfig({ agent, executor, agentName, promptFileName, overlayDir }) {
|
|
137
|
+
function buildOpenCodeConfig({ agent, executor, agentName, promptFileName, overlayDir, skillProjection }) {
|
|
138
138
|
const promptAgent = {
|
|
139
139
|
description: `Wave agent ${agent.agentId}: ${agent.title}`,
|
|
140
140
|
mode: "primary",
|
|
@@ -149,7 +149,11 @@ function buildOpenCodeConfig({ agent, executor, agentName, promptFileName, overl
|
|
|
149
149
|
const baseAgentConfig = isPlainObject(baseConfig.agent) ? baseConfig.agent : {};
|
|
150
150
|
const config = mergeJsonObjects(baseConfig, {
|
|
151
151
|
$schema: baseConfig.$schema || "https://opencode.ai/config.json",
|
|
152
|
-
instructions: mergeUniqueStringArrays(
|
|
152
|
+
instructions: mergeUniqueStringArrays(
|
|
153
|
+
baseConfig.instructions,
|
|
154
|
+
executor.opencode.instructions,
|
|
155
|
+
skillProjection?.opencodeInstructions,
|
|
156
|
+
),
|
|
153
157
|
agent: {
|
|
154
158
|
...baseAgentConfig,
|
|
155
159
|
[agentName]: mergeJsonObjects(baseAgentConfig[agentName], promptAgent),
|
|
@@ -201,7 +205,11 @@ export function buildCodexExecInvocation(
|
|
|
201
205
|
function buildClaudeLaunchSpec({ agent, promptPath, logPath, overlayDir }) {
|
|
202
206
|
const executor = agent.executorResolved;
|
|
203
207
|
const systemPromptPath = path.join(overlayDir, "claude-system-prompt.txt");
|
|
204
|
-
|
|
208
|
+
const skillText = String(agent?.skillsResolved?.promptText || "").trim();
|
|
209
|
+
writeTextAtomic(
|
|
210
|
+
systemPromptPath,
|
|
211
|
+
`${renderHarnessSystemPrompt(agent, "claude")}${skillText ? `\n\n${skillText}` : ""}\n`,
|
|
212
|
+
);
|
|
205
213
|
const tokens = [executor.claude.command, "-p", "--no-session-persistence"];
|
|
206
214
|
const settingsPath = buildClaudeSettingsPath(executor, overlayDir);
|
|
207
215
|
appendSingleValueFlag(tokens, "--output-format", executor.claude.outputFormat || "text");
|
|
@@ -234,7 +242,7 @@ function buildClaudeLaunchSpec({ agent, promptPath, logPath, overlayDir }) {
|
|
|
234
242
|
};
|
|
235
243
|
}
|
|
236
244
|
|
|
237
|
-
function buildOpenCodeLaunchSpec({ agent, promptPath, logPath, overlayDir }) {
|
|
245
|
+
function buildOpenCodeLaunchSpec({ agent, promptPath, logPath, overlayDir, skillProjection }) {
|
|
238
246
|
const executor = agent.executorResolved;
|
|
239
247
|
const requestedAgentName = String(executor.opencode.agent || `wave-${agent.agentId}`)
|
|
240
248
|
.trim()
|
|
@@ -252,12 +260,17 @@ function buildOpenCodeLaunchSpec({ agent, promptPath, logPath, overlayDir }) {
|
|
|
252
260
|
agentName,
|
|
253
261
|
promptFileName,
|
|
254
262
|
overlayDir,
|
|
263
|
+
skillProjection,
|
|
255
264
|
});
|
|
256
265
|
const tokens = [executor.opencode.command, "run", "--agent", shellQuote(agentName)];
|
|
257
266
|
appendSingleValueFlag(tokens, "--model", executor.opencode.model || executor.model);
|
|
258
267
|
appendSingleValueFlag(tokens, "--format", executor.opencode.format || "default");
|
|
259
268
|
appendSingleValueFlag(tokens, "--attach", executor.opencode.attach);
|
|
260
|
-
appendRepeatedFlag(
|
|
269
|
+
appendRepeatedFlag(
|
|
270
|
+
tokens,
|
|
271
|
+
"--file",
|
|
272
|
+
mergeUniqueStringArrays(executor.opencode.files, skillProjection?.opencodeFiles),
|
|
273
|
+
);
|
|
261
274
|
appendSingleValueFlag(tokens, "--title", `wave-${agent.agentId}`);
|
|
262
275
|
return {
|
|
263
276
|
executorId: "opencode",
|
|
@@ -286,7 +299,7 @@ function buildLocalLaunchSpec({ promptPath, logPath }) {
|
|
|
286
299
|
};
|
|
287
300
|
}
|
|
288
301
|
|
|
289
|
-
function buildCodexLaunchSpec({ agent, promptPath, logPath }) {
|
|
302
|
+
function buildCodexLaunchSpec({ agent, promptPath, logPath, skillProjection }) {
|
|
290
303
|
const executor = agent.executorResolved;
|
|
291
304
|
return {
|
|
292
305
|
executorId: "codex",
|
|
@@ -304,7 +317,7 @@ function buildCodexLaunchSpec({ agent, promptPath, logPath }) {
|
|
|
304
317
|
config: executor.codex.config,
|
|
305
318
|
search: executor.codex.search,
|
|
306
319
|
images: executor.codex.images,
|
|
307
|
-
addDirs: executor.codex.addDirs,
|
|
320
|
+
addDirs: mergeUniqueStringArrays(executor.codex.addDirs, skillProjection?.codexAddDirs),
|
|
308
321
|
json: executor.codex.json,
|
|
309
322
|
ephemeral: executor.codex.ephemeral,
|
|
310
323
|
},
|
|
@@ -313,19 +326,19 @@ function buildCodexLaunchSpec({ agent, promptPath, logPath }) {
|
|
|
313
326
|
};
|
|
314
327
|
}
|
|
315
328
|
|
|
316
|
-
export function buildExecutorLaunchSpec({ agent, promptPath, logPath, overlayDir }) {
|
|
329
|
+
export function buildExecutorLaunchSpec({ agent, promptPath, logPath, overlayDir, skillProjection }) {
|
|
317
330
|
const executorId = normalizeExecutorMode(agent?.executorResolved?.id || DEFAULT_EXECUTOR_MODE);
|
|
318
331
|
ensureDirectory(overlayDir);
|
|
319
332
|
if (executorId === "local") {
|
|
320
333
|
return buildLocalLaunchSpec({ promptPath, logPath });
|
|
321
334
|
}
|
|
322
335
|
if (executorId === "claude") {
|
|
323
|
-
return buildClaudeLaunchSpec({ agent, promptPath, logPath, overlayDir });
|
|
336
|
+
return buildClaudeLaunchSpec({ agent, promptPath, logPath, overlayDir, skillProjection });
|
|
324
337
|
}
|
|
325
338
|
if (executorId === "opencode") {
|
|
326
|
-
return buildOpenCodeLaunchSpec({ agent, promptPath, logPath, overlayDir });
|
|
339
|
+
return buildOpenCodeLaunchSpec({ agent, promptPath, logPath, overlayDir, skillProjection });
|
|
327
340
|
}
|
|
328
|
-
return buildCodexLaunchSpec({ agent, promptPath, logPath });
|
|
341
|
+
return buildCodexLaunchSpec({ agent, promptPath, logPath, skillProjection });
|
|
329
342
|
}
|
|
330
343
|
|
|
331
344
|
export function commandForExecutor(executor, executorId = executor?.id) {
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
import { buildLanePaths, ensureDirectory, PACKAGE_ROOT, readJsonOrNull, REPO_ROOT, writeJsonAtomic } from "./shared.mjs";
|
|
8
8
|
import { loadWaveConfig } from "./config.mjs";
|
|
9
9
|
import { applyExecutorSelectionsToWave, parseWaveFiles, validateWaveDefinition } from "./wave-files.mjs";
|
|
10
|
+
import { validateLaneSkillConfiguration } from "./skills.mjs";
|
|
10
11
|
|
|
11
12
|
export const INSTALL_STATE_SCHEMA_VERSION = 1;
|
|
12
13
|
export const INSTALL_STATE_DIR = ".wave";
|
|
@@ -16,10 +17,17 @@ export const CHANGELOG_MANIFEST_PATH = path.join(PACKAGE_ROOT, "releases", "mani
|
|
|
16
17
|
export const PACKAGE_METADATA_PATH = path.join(PACKAGE_ROOT, "package.json");
|
|
17
18
|
export const STARTER_TEMPLATE_PATHS = [
|
|
18
19
|
"wave.config.json",
|
|
20
|
+
"docs/README.md",
|
|
19
21
|
"docs/agents/wave-documentation-role.md",
|
|
20
22
|
"docs/agents/wave-evaluator-role.md",
|
|
21
23
|
"docs/agents/wave-integration-role.md",
|
|
24
|
+
"docs/concepts/context7-vs-skills.md",
|
|
25
|
+
"docs/concepts/operating-modes.md",
|
|
26
|
+
"docs/concepts/runtime-agnostic-orchestration.md",
|
|
27
|
+
"docs/concepts/what-is-a-wave.md",
|
|
22
28
|
"docs/context7/bundles.json",
|
|
29
|
+
"docs/guides/planner.md",
|
|
30
|
+
"docs/guides/terminal-surfaces.md",
|
|
23
31
|
"docs/plans/component-cutover-matrix.json",
|
|
24
32
|
"docs/plans/component-cutover-matrix.md",
|
|
25
33
|
"docs/plans/context7-wave-orchestrator.md",
|
|
@@ -29,6 +37,7 @@ export const STARTER_TEMPLATE_PATHS = [
|
|
|
29
37
|
"docs/plans/wave-orchestrator.md",
|
|
30
38
|
"docs/plans/waves/wave-0.md",
|
|
31
39
|
"docs/reference/repository-guidance.md",
|
|
40
|
+
"docs/reference/skills.md",
|
|
32
41
|
"docs/reference/runtime-config/README.md",
|
|
33
42
|
"docs/reference/runtime-config/codex.md",
|
|
34
43
|
"docs/reference/runtime-config/claude.md",
|
|
@@ -37,6 +46,8 @@ export const STARTER_TEMPLATE_PATHS = [
|
|
|
37
46
|
];
|
|
38
47
|
const REQUIRED_GITIGNORE_ENTRIES = [
|
|
39
48
|
".tmp/",
|
|
49
|
+
".wave/",
|
|
50
|
+
".vscode/terminals.json",
|
|
40
51
|
"docs/research/cache/",
|
|
41
52
|
"docs/research/agent-context-cache/",
|
|
42
53
|
"docs/research/papers/",
|
|
@@ -69,7 +80,7 @@ function ensureWorkspaceSubdir(relPath) {
|
|
|
69
80
|
}
|
|
70
81
|
|
|
71
82
|
function templateStatusList() {
|
|
72
|
-
return
|
|
83
|
+
return starterTemplatePaths().map((relPath) => ({
|
|
73
84
|
path: relPath,
|
|
74
85
|
sourcePath: path.join(PACKAGE_ROOT, relPath),
|
|
75
86
|
targetPath: path.join(REPO_ROOT, relPath),
|
|
@@ -77,6 +88,30 @@ function templateStatusList() {
|
|
|
77
88
|
}));
|
|
78
89
|
}
|
|
79
90
|
|
|
91
|
+
function starterSkillTemplatePaths() {
|
|
92
|
+
const skillsRoot = path.join(PACKAGE_ROOT, "skills");
|
|
93
|
+
if (!fs.existsSync(skillsRoot)) {
|
|
94
|
+
return [];
|
|
95
|
+
}
|
|
96
|
+
const files = [];
|
|
97
|
+
const visit = (targetDir) => {
|
|
98
|
+
for (const entry of fs.readdirSync(targetDir, { withFileTypes: true })) {
|
|
99
|
+
const fullPath = path.join(targetDir, entry.name);
|
|
100
|
+
if (entry.isDirectory()) {
|
|
101
|
+
visit(fullPath);
|
|
102
|
+
} else {
|
|
103
|
+
files.push(path.relative(PACKAGE_ROOT, fullPath).replaceAll(path.sep, "/"));
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
visit(skillsRoot);
|
|
108
|
+
return files.toSorted();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function starterTemplatePaths() {
|
|
112
|
+
return [...STARTER_TEMPLATE_PATHS, ...starterSkillTemplatePaths()];
|
|
113
|
+
}
|
|
114
|
+
|
|
80
115
|
function existingBootstrapMarkers() {
|
|
81
116
|
return templateStatusList()
|
|
82
117
|
.filter((entry) => entry.exists)
|
|
@@ -242,6 +277,10 @@ export function runDoctor() {
|
|
|
242
277
|
errors.push(`Missing required Wave file: ${relPath}`);
|
|
243
278
|
}
|
|
244
279
|
}
|
|
280
|
+
const skillValidation = validateLaneSkillConfiguration(lanePaths.laneProfile);
|
|
281
|
+
if (!skillValidation.ok) {
|
|
282
|
+
errors.push(...skillValidation.errors);
|
|
283
|
+
}
|
|
245
284
|
if (fs.existsSync(lanePaths.wavesDir)) {
|
|
246
285
|
const context7BundleIndex = loadContext7BundleIndex(lanePaths.context7BundleIndexPath);
|
|
247
286
|
parseWaveFiles(lanePaths.wavesDir, { laneProfile: lanePaths.laneProfile })
|
|
@@ -314,7 +353,7 @@ export function initializeWorkspace(options = {}) {
|
|
|
314
353
|
if (adoptExisting) {
|
|
315
354
|
adoptedFiles.push(...markers);
|
|
316
355
|
} else {
|
|
317
|
-
for (const relPath of
|
|
356
|
+
for (const relPath of starterTemplatePaths()) {
|
|
318
357
|
copyTemplateFile(relPath);
|
|
319
358
|
seededFiles.push(relPath);
|
|
320
359
|
}
|