@juancr11/sibu 0.16.0 → 0.17.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 +66 -29
- package/bin/entrypoints/cli/create-program.js +1 -1
- package/bin/entrypoints/cli/execute-command.js +4 -7
- package/bin/modules/agent-tool-configuration/index.js +1 -0
- package/bin/modules/agent-tool-configuration/mcp-config.js +134 -0
- package/bin/modules/interactive-guidance/prompts.js +1 -1
- package/bin/modules/mcp-server-selection-management/list-mcp-servers/handler.js +2 -2
- package/bin/modules/mcp-server-selection-management/stop-mcp-server/handler.js +5 -5
- package/bin/modules/mcp-server-selection-management/use-mcp-server/handler.js +4 -3
- package/bin/modules/skill-selection-management/list-skills/handler.js +2 -2
- package/bin/modules/skill-selection-management/stop-managing-file/handler.js +5 -4
- package/bin/modules/skill-selection-management/use-skill/handler.js +5 -4
- package/bin/modules/{sync-review → sync-review-orchestrator}/action-prompt.js +14 -1
- package/bin/modules/{sync-review → sync-review-orchestrator}/apply-action.js +4 -3
- package/bin/modules/sync-review-orchestrator/handler.js +124 -0
- package/bin/modules/{sync-review → sync-review-orchestrator}/index.js +2 -0
- package/bin/modules/{sync-review → sync-review-orchestrator}/log-preview.js +1 -1
- package/bin/modules/{sync-review → sync-review-orchestrator}/sync-preview.js +3 -3
- package/bin/modules/sync-review-orchestrator/unsupported-agent-cleanup.js +57 -0
- package/bin/modules/{workflow-mutation-readiness → sync-review-orchestrator}/workflow-mutation-readiness.js +12 -3
- package/bin/modules/{workflow-target-planning → template-catalog}/catalog.js +83 -26
- package/bin/modules/{workflow-target-planning → template-catalog}/index.js +2 -1
- package/bin/modules/template-catalog/templates.js +154 -0
- package/bin/modules/workflow-configuration-manager/index.js +6 -0
- package/bin/modules/workflow-configuration-manager/list-mcp-servers/handler.js +46 -0
- package/bin/modules/workflow-configuration-manager/list-skills/command.js +1 -0
- package/bin/modules/workflow-configuration-manager/list-skills/handler.js +75 -0
- package/bin/modules/workflow-configuration-manager/stop-managing-file/command.js +1 -0
- package/bin/modules/workflow-configuration-manager/stop-managing-file/handler.js +221 -0
- package/bin/modules/workflow-configuration-manager/stop-mcp-server/command.js +1 -0
- package/bin/modules/workflow-configuration-manager/stop-mcp-server/handler.js +198 -0
- package/bin/modules/workflow-configuration-manager/use-mcp-server/command.js +1 -0
- package/bin/modules/workflow-configuration-manager/use-mcp-server/handler.js +193 -0
- package/bin/modules/workflow-configuration-manager/use-skill/command.js +1 -0
- package/bin/modules/workflow-configuration-manager/use-skill/handler.js +314 -0
- package/bin/modules/workflow-health-inspector/command.js +1 -0
- package/bin/modules/{workflow-health-diagnosis → workflow-health-inspector}/handler.js +7 -7
- package/bin/modules/workflow-installer/command.js +1 -0
- package/bin/modules/{project-adoption → workflow-installer}/handler.js +5 -4
- package/bin/modules/workflow-state-ledger/index.js +2 -0
- package/bin/modules/workflow-state-ledger/state-path.js +1 -0
- package/bin/modules/{workflow-state-registry → workflow-state-ledger}/state.js +40 -1
- package/bin/{modules/workflow-target-planning/workflow-targets.js → shared/expected-workflow-targets.js} +3 -103
- package/bin/shared/paths.js +1 -1
- package/bin/support/expected-workflow-targets.js +131 -0
- package/bin/support/interactive-guidance/index.js +1 -0
- package/bin/support/interactive-guidance/prompts.js +275 -0
- package/bin/support/version-advisory/index.js +1 -0
- package/bin/support/version-advisory/npm-version.js +205 -0
- package/package.json +2 -1
- package/templates/.claude/agents/sibu-implementation-executor.md +30 -0
- package/templates/.claude/agents/sibu-implementation-planner.md +30 -0
- package/templates/.codex/agents/sibu-implementation-executor.toml +30 -0
- package/templates/.codex/agents/sibu-implementation-planner.toml +30 -0
- package/templates/.gemini/agents/sibu-implementation-executor.md +30 -0
- package/templates/.gemini/agents/sibu-implementation-planner.md +30 -0
- package/templates/AGENTS.md +4 -2
- package/templates/manifest.json +94 -17
- package/templates/skills/ai-implementation-executor-toolbox/SKILL.md +78 -0
- package/templates/skills/ai-implementation-plan-executor/SKILL.md +64 -108
- package/templates/skills/ai-implementation-planner/SKILL.md +55 -138
- package/templates/skills/ai-implementation-planner-toolbox/SKILL.md +78 -0
- package/templates/skills/business-domain-model-writer/SKILL.md +313 -0
- package/templates/skills/capabilities-map-writer/SKILL.md +271 -0
- package/templates/skills/deep-module-map-writer/SKILL.md +50 -14
- package/templates/skills/feature-brief-writer/SKILL.md +72 -32
- package/templates/skills/technical-design-writer/SKILL.md +10 -10
- package/templates/skills/ux-expert/SKILL.md +62 -17
- package/bin/modules/sync-review/handler.js +0 -77
- package/bin/modules/template-catalog-rendering/index.js +0 -1
- package/bin/modules/template-catalog-rendering/templates.js +0 -163
- package/bin/modules/workflow-mutation-readiness/index.js +0 -1
- package/bin/modules/workflow-state-registry/index.js +0 -1
- /package/bin/{modules/project-adoption/command.js → entrypoints/cli-command-surface/index.js} +0 -0
- /package/bin/modules/{sync-review → sync-review-orchestrator}/command.js +0 -0
- /package/bin/modules/{workflow-health-diagnosis → workflow-configuration-manager/list-mcp-servers}/command.js +0 -0
- /package/bin/modules/{workflow-health-diagnosis → workflow-health-inspector}/index.js +0 -0
- /package/bin/modules/{project-adoption → workflow-installer}/index.js +0 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { getSelectedAgentsFromState, getSelectedArchitectureSkillFromState, getSelectedDatabaseSkillsFromState, getSelectedFrameworkSkillsFromState, getSelectedLanguageSkillsFromState, getSelectedMcpServersFromState, getSelectedWorkflowSkillsFromState, getWorkflowTargets, SUPPORTED_AGENTS, } from '../template-catalog/index.js';
|
|
4
|
+
import { cloneState } from '../workflow-state-ledger/index.js';
|
|
5
|
+
export function getUnsupportedAgentCleanupPlan({ rootPath, state }) {
|
|
6
|
+
const supportedAgentIds = new Set(SUPPORTED_AGENTS.map((agent) => agent.id));
|
|
7
|
+
const unsupportedAgentIds = state.selectedAgents.filter((agentId) => !supportedAgentIds.has(agentId));
|
|
8
|
+
if (unsupportedAgentIds.length === 0) {
|
|
9
|
+
return undefined;
|
|
10
|
+
}
|
|
11
|
+
const remainingSupportedAgents = getSelectedAgentsFromState(state);
|
|
12
|
+
const obsoleteManagedFilePaths = getObsoleteManagedFilePaths({ rootPath, state, remainingSupportedAgents });
|
|
13
|
+
const filePathsToDelete = obsoleteManagedFilePaths.filter((relativePath) => state.managedFiles[relativePath]?.status !== 'unmanaged');
|
|
14
|
+
return {
|
|
15
|
+
unsupportedAgentIds,
|
|
16
|
+
remainingSupportedAgents,
|
|
17
|
+
obsoleteManagedFilePaths,
|
|
18
|
+
filePathsToDelete,
|
|
19
|
+
removesSibuState: remainingSupportedAgents.length === 0,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export function applyUnsupportedAgentCleanup({ rootPath, statePath, state, plan, }) {
|
|
23
|
+
const removedFiles = [];
|
|
24
|
+
for (const relativePath of plan.filePathsToDelete) {
|
|
25
|
+
const targetPath = path.join(rootPath, relativePath);
|
|
26
|
+
if (!fs.existsSync(targetPath)) {
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
fs.rmSync(targetPath, { recursive: true, force: true });
|
|
30
|
+
removedFiles.push(relativePath);
|
|
31
|
+
}
|
|
32
|
+
if (plan.removesSibuState) {
|
|
33
|
+
fs.rmSync(statePath, { force: true });
|
|
34
|
+
return { removedStateFile: true, removedFiles };
|
|
35
|
+
}
|
|
36
|
+
const unsupportedAgentIds = new Set(plan.unsupportedAgentIds);
|
|
37
|
+
const obsoleteManagedFilePaths = new Set(plan.obsoleteManagedFilePaths);
|
|
38
|
+
const nextState = cloneState(state);
|
|
39
|
+
nextState.selectedAgents = nextState.selectedAgents.filter((agentId) => !unsupportedAgentIds.has(agentId));
|
|
40
|
+
nextState.updatedAt = new Date().toISOString();
|
|
41
|
+
for (const relativePath of obsoleteManagedFilePaths) {
|
|
42
|
+
delete nextState.managedFiles[relativePath];
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
removedStateFile: false,
|
|
46
|
+
removedFiles,
|
|
47
|
+
state: nextState,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function getObsoleteManagedFilePaths({ rootPath, state, remainingSupportedAgents, }) {
|
|
51
|
+
if (remainingSupportedAgents.length === 0) {
|
|
52
|
+
return Object.keys(state.managedFiles);
|
|
53
|
+
}
|
|
54
|
+
const expectedTargets = getWorkflowTargets(rootPath, remainingSupportedAgents, getSelectedLanguageSkillsFromState(state), getSelectedFrameworkSkillsFromState(state), getSelectedArchitectureSkillFromState(state), getSelectedWorkflowSkillsFromState(state), getSelectedDatabaseSkillsFromState(state), getSelectedMcpServersFromState(state));
|
|
55
|
+
const expectedManagedFilePaths = new Set(expectedTargets.map((target) => path.relative(rootPath, target.targetPath)));
|
|
56
|
+
return Object.keys(state.managedFiles).filter((relativePath) => !expectedManagedFilePaths.has(relativePath));
|
|
57
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { readTemplateManifest } from '../template-catalog/index.js';
|
|
2
|
+
import { readStateForDoctor } from '../workflow-state-ledger/index.js';
|
|
3
|
+
import { getSyncPreviews, isActionableSyncPreview } from './sync-preview.js';
|
|
4
|
+
import { getUnsupportedAgentCleanupPlan } from './unsupported-agent-cleanup.js';
|
|
4
5
|
export function getWorkflowMutationReadiness({ rootPath, statePath }) {
|
|
5
6
|
const stateResult = readStateForDoctor(statePath);
|
|
6
7
|
if (!stateResult.ok) {
|
|
@@ -11,6 +12,14 @@ export function getWorkflowMutationReadiness({ rootPath, statePath }) {
|
|
|
11
12
|
};
|
|
12
13
|
}
|
|
13
14
|
const manifest = readTemplateManifest();
|
|
15
|
+
const unsupportedAgentCleanupPlan = getUnsupportedAgentCleanupPlan({ rootPath, state: stateResult.state });
|
|
16
|
+
if (unsupportedAgentCleanupPlan) {
|
|
17
|
+
return {
|
|
18
|
+
ok: false,
|
|
19
|
+
message: 'Workflow state is not clean enough to select a skill safely.',
|
|
20
|
+
hint: 'Run `sibu sync` to review workflow state before selecting a skill.',
|
|
21
|
+
};
|
|
22
|
+
}
|
|
14
23
|
const previews = getSyncPreviews({ rootPath, state: stateResult.state, manifest });
|
|
15
24
|
const actionablePreviews = previews.filter(isActionableSyncPreview);
|
|
16
25
|
if (actionablePreviews.length > 0) {
|
|
@@ -5,7 +5,6 @@ export const MANDATORY_SKILLS = [
|
|
|
5
5
|
codex: '.agents/skills/clean-code/SKILL.md',
|
|
6
6
|
gemini: '.agents/skills/clean-code/SKILL.md',
|
|
7
7
|
claude: '.agents/skills/clean-code/SKILL.md',
|
|
8
|
-
windsurf: '.agents/skills/clean-code/SKILL.md',
|
|
9
8
|
},
|
|
10
9
|
},
|
|
11
10
|
{
|
|
@@ -14,7 +13,22 @@ export const MANDATORY_SKILLS = [
|
|
|
14
13
|
codex: '.agents/skills/product-vision-writer/SKILL.md',
|
|
15
14
|
gemini: '.agents/skills/product-vision-writer/SKILL.md',
|
|
16
15
|
claude: '.agents/skills/product-vision-writer/SKILL.md',
|
|
17
|
-
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
templateRelativePath: 'skills/business-domain-model-writer/SKILL.md',
|
|
20
|
+
targetRelativePathsByAgent: {
|
|
21
|
+
codex: '.agents/skills/business-domain-model-writer/SKILL.md',
|
|
22
|
+
gemini: '.agents/skills/business-domain-model-writer/SKILL.md',
|
|
23
|
+
claude: '.agents/skills/business-domain-model-writer/SKILL.md',
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
templateRelativePath: 'skills/capabilities-map-writer/SKILL.md',
|
|
28
|
+
targetRelativePathsByAgent: {
|
|
29
|
+
codex: '.agents/skills/capabilities-map-writer/SKILL.md',
|
|
30
|
+
gemini: '.agents/skills/capabilities-map-writer/SKILL.md',
|
|
31
|
+
claude: '.agents/skills/capabilities-map-writer/SKILL.md',
|
|
18
32
|
},
|
|
19
33
|
},
|
|
20
34
|
{
|
|
@@ -23,7 +37,6 @@ export const MANDATORY_SKILLS = [
|
|
|
23
37
|
codex: '.agents/skills/deep-module-map-writer/SKILL.md',
|
|
24
38
|
gemini: '.agents/skills/deep-module-map-writer/SKILL.md',
|
|
25
39
|
claude: '.agents/skills/deep-module-map-writer/SKILL.md',
|
|
26
|
-
windsurf: '.agents/skills/deep-module-map-writer/SKILL.md',
|
|
27
40
|
},
|
|
28
41
|
},
|
|
29
42
|
{
|
|
@@ -32,7 +45,6 @@ export const MANDATORY_SKILLS = [
|
|
|
32
45
|
codex: '.agents/skills/feature-brief-writer/SKILL.md',
|
|
33
46
|
gemini: '.agents/skills/feature-brief-writer/SKILL.md',
|
|
34
47
|
claude: '.agents/skills/feature-brief-writer/SKILL.md',
|
|
35
|
-
windsurf: '.agents/skills/feature-brief-writer/SKILL.md',
|
|
36
48
|
},
|
|
37
49
|
},
|
|
38
50
|
{
|
|
@@ -41,7 +53,6 @@ export const MANDATORY_SKILLS = [
|
|
|
41
53
|
codex: '.agents/skills/technical-design-writer/SKILL.md',
|
|
42
54
|
gemini: '.agents/skills/technical-design-writer/SKILL.md',
|
|
43
55
|
claude: '.agents/skills/technical-design-writer/SKILL.md',
|
|
44
|
-
windsurf: '.agents/skills/technical-design-writer/SKILL.md',
|
|
45
56
|
},
|
|
46
57
|
},
|
|
47
58
|
{
|
|
@@ -50,7 +61,6 @@ export const MANDATORY_SKILLS = [
|
|
|
50
61
|
codex: '.agents/skills/scrum-master-planner/SKILL.md',
|
|
51
62
|
gemini: '.agents/skills/scrum-master-planner/SKILL.md',
|
|
52
63
|
claude: '.agents/skills/scrum-master-planner/SKILL.md',
|
|
53
|
-
windsurf: '.agents/skills/scrum-master-planner/SKILL.md',
|
|
54
64
|
},
|
|
55
65
|
},
|
|
56
66
|
{
|
|
@@ -59,7 +69,38 @@ export const MANDATORY_SKILLS = [
|
|
|
59
69
|
codex: '.agents/skills/ai-implementation-planner/SKILL.md',
|
|
60
70
|
gemini: '.agents/skills/ai-implementation-planner/SKILL.md',
|
|
61
71
|
claude: '.agents/skills/ai-implementation-planner/SKILL.md',
|
|
62
|
-
|
|
72
|
+
},
|
|
73
|
+
supplementalTargetsByAgent: {
|
|
74
|
+
codex: [
|
|
75
|
+
{
|
|
76
|
+
templateRelativePath: 'skills/ai-implementation-planner-toolbox/SKILL.md',
|
|
77
|
+
targetRelativePath: '.agents/skills/ai-implementation-planner-toolbox/SKILL.md',
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
templateRelativePath: '.codex/agents/sibu-implementation-planner.toml',
|
|
81
|
+
targetRelativePath: '.codex/agents/sibu-implementation-planner.toml',
|
|
82
|
+
},
|
|
83
|
+
],
|
|
84
|
+
gemini: [
|
|
85
|
+
{
|
|
86
|
+
templateRelativePath: 'skills/ai-implementation-planner-toolbox/SKILL.md',
|
|
87
|
+
targetRelativePath: '.agents/skills/ai-implementation-planner-toolbox/SKILL.md',
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
templateRelativePath: '.gemini/agents/sibu-implementation-planner.md',
|
|
91
|
+
targetRelativePath: '.gemini/agents/sibu-implementation-planner.md',
|
|
92
|
+
},
|
|
93
|
+
],
|
|
94
|
+
claude: [
|
|
95
|
+
{
|
|
96
|
+
templateRelativePath: 'skills/ai-implementation-planner-toolbox/SKILL.md',
|
|
97
|
+
targetRelativePath: '.agents/skills/ai-implementation-planner-toolbox/SKILL.md',
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
templateRelativePath: '.claude/agents/sibu-implementation-planner.md',
|
|
101
|
+
targetRelativePath: '.claude/agents/sibu-implementation-planner.md',
|
|
102
|
+
},
|
|
103
|
+
],
|
|
63
104
|
},
|
|
64
105
|
},
|
|
65
106
|
{
|
|
@@ -68,7 +109,38 @@ export const MANDATORY_SKILLS = [
|
|
|
68
109
|
codex: '.agents/skills/ai-implementation-plan-executor/SKILL.md',
|
|
69
110
|
gemini: '.agents/skills/ai-implementation-plan-executor/SKILL.md',
|
|
70
111
|
claude: '.agents/skills/ai-implementation-plan-executor/SKILL.md',
|
|
71
|
-
|
|
112
|
+
},
|
|
113
|
+
supplementalTargetsByAgent: {
|
|
114
|
+
codex: [
|
|
115
|
+
{
|
|
116
|
+
templateRelativePath: 'skills/ai-implementation-executor-toolbox/SKILL.md',
|
|
117
|
+
targetRelativePath: '.agents/skills/ai-implementation-executor-toolbox/SKILL.md',
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
templateRelativePath: '.codex/agents/sibu-implementation-executor.toml',
|
|
121
|
+
targetRelativePath: '.codex/agents/sibu-implementation-executor.toml',
|
|
122
|
+
},
|
|
123
|
+
],
|
|
124
|
+
gemini: [
|
|
125
|
+
{
|
|
126
|
+
templateRelativePath: 'skills/ai-implementation-executor-toolbox/SKILL.md',
|
|
127
|
+
targetRelativePath: '.agents/skills/ai-implementation-executor-toolbox/SKILL.md',
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
templateRelativePath: '.gemini/agents/sibu-implementation-executor.md',
|
|
131
|
+
targetRelativePath: '.gemini/agents/sibu-implementation-executor.md',
|
|
132
|
+
},
|
|
133
|
+
],
|
|
134
|
+
claude: [
|
|
135
|
+
{
|
|
136
|
+
templateRelativePath: 'skills/ai-implementation-executor-toolbox/SKILL.md',
|
|
137
|
+
targetRelativePath: '.agents/skills/ai-implementation-executor-toolbox/SKILL.md',
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
templateRelativePath: '.claude/agents/sibu-implementation-executor.md',
|
|
141
|
+
targetRelativePath: '.claude/agents/sibu-implementation-executor.md',
|
|
142
|
+
},
|
|
143
|
+
],
|
|
72
144
|
},
|
|
73
145
|
},
|
|
74
146
|
{
|
|
@@ -77,7 +149,6 @@ export const MANDATORY_SKILLS = [
|
|
|
77
149
|
codex: '.agents/skills/feature-idea-capture/SKILL.md',
|
|
78
150
|
gemini: '.agents/skills/feature-idea-capture/SKILL.md',
|
|
79
151
|
claude: '.agents/skills/feature-idea-capture/SKILL.md',
|
|
80
|
-
windsurf: '.agents/skills/feature-idea-capture/SKILL.md',
|
|
81
152
|
},
|
|
82
153
|
},
|
|
83
154
|
];
|
|
@@ -109,7 +180,6 @@ export const SELECTABLE_LANGUAGE_SKILLS = [
|
|
|
109
180
|
codex: '.agents/skills/typescript/SKILL.md',
|
|
110
181
|
gemini: '.agents/skills/typescript/SKILL.md',
|
|
111
182
|
claude: '.agents/skills/typescript/SKILL.md',
|
|
112
|
-
windsurf: '.agents/skills/typescript/SKILL.md',
|
|
113
183
|
},
|
|
114
184
|
},
|
|
115
185
|
{
|
|
@@ -122,7 +192,6 @@ export const SELECTABLE_LANGUAGE_SKILLS = [
|
|
|
122
192
|
codex: '.agents/skills/golang/SKILL.md',
|
|
123
193
|
gemini: '.agents/skills/golang/SKILL.md',
|
|
124
194
|
claude: '.agents/skills/golang/SKILL.md',
|
|
125
|
-
windsurf: '.agents/skills/golang/SKILL.md',
|
|
126
195
|
},
|
|
127
196
|
},
|
|
128
197
|
];
|
|
@@ -137,7 +206,6 @@ export const SELECTABLE_DATABASE_SKILLS = [
|
|
|
137
206
|
codex: '.agents/skills/postgresql-expert/SKILL.md',
|
|
138
207
|
gemini: '.agents/skills/postgresql-expert/SKILL.md',
|
|
139
208
|
claude: '.agents/skills/postgresql-expert/SKILL.md',
|
|
140
|
-
windsurf: '.agents/skills/postgresql-expert/SKILL.md',
|
|
141
209
|
},
|
|
142
210
|
},
|
|
143
211
|
];
|
|
@@ -152,7 +220,6 @@ export const SELECTABLE_FRAMEWORK_SKILLS = [
|
|
|
152
220
|
codex: '.agents/skills/react/SKILL.md',
|
|
153
221
|
gemini: '.agents/skills/react/SKILL.md',
|
|
154
222
|
claude: '.agents/skills/react/SKILL.md',
|
|
155
|
-
windsurf: '.agents/skills/react/SKILL.md',
|
|
156
223
|
},
|
|
157
224
|
},
|
|
158
225
|
{
|
|
@@ -165,7 +232,6 @@ export const SELECTABLE_FRAMEWORK_SKILLS = [
|
|
|
165
232
|
codex: '.agents/skills/nextjs/SKILL.md',
|
|
166
233
|
gemini: '.agents/skills/nextjs/SKILL.md',
|
|
167
234
|
claude: '.agents/skills/nextjs/SKILL.md',
|
|
168
|
-
windsurf: '.agents/skills/nextjs/SKILL.md',
|
|
169
235
|
},
|
|
170
236
|
},
|
|
171
237
|
];
|
|
@@ -180,7 +246,6 @@ export const SELECTABLE_ARCHITECTURE_SKILLS = [
|
|
|
180
246
|
codex: '.agents/skills/ddd-hexagonal/SKILL.md',
|
|
181
247
|
gemini: '.agents/skills/ddd-hexagonal/SKILL.md',
|
|
182
248
|
claude: '.agents/skills/ddd-hexagonal/SKILL.md',
|
|
183
|
-
windsurf: '.agents/skills/ddd-hexagonal/SKILL.md',
|
|
184
249
|
},
|
|
185
250
|
},
|
|
186
251
|
{
|
|
@@ -193,7 +258,6 @@ export const SELECTABLE_ARCHITECTURE_SKILLS = [
|
|
|
193
258
|
codex: '.agents/skills/command-pattern/SKILL.md',
|
|
194
259
|
gemini: '.agents/skills/command-pattern/SKILL.md',
|
|
195
260
|
claude: '.agents/skills/command-pattern/SKILL.md',
|
|
196
|
-
windsurf: '.agents/skills/command-pattern/SKILL.md',
|
|
197
261
|
},
|
|
198
262
|
},
|
|
199
263
|
{
|
|
@@ -206,7 +270,6 @@ export const SELECTABLE_ARCHITECTURE_SKILLS = [
|
|
|
206
270
|
codex: '.agents/skills/layered-architecture/SKILL.md',
|
|
207
271
|
gemini: '.agents/skills/layered-architecture/SKILL.md',
|
|
208
272
|
claude: '.agents/skills/layered-architecture/SKILL.md',
|
|
209
|
-
windsurf: '.agents/skills/layered-architecture/SKILL.md',
|
|
210
273
|
},
|
|
211
274
|
},
|
|
212
275
|
];
|
|
@@ -221,7 +284,6 @@ export const SELECTABLE_WORKFLOW_SKILLS = [
|
|
|
221
284
|
codex: '.agents/skills/ai-prompt-engineer-master/SKILL.md',
|
|
222
285
|
gemini: '.agents/skills/ai-prompt-engineer-master/SKILL.md',
|
|
223
286
|
claude: '.agents/skills/ai-prompt-engineer-master/SKILL.md',
|
|
224
|
-
windsurf: '.agents/skills/ai-prompt-engineer-master/SKILL.md',
|
|
225
287
|
},
|
|
226
288
|
},
|
|
227
289
|
{
|
|
@@ -234,7 +296,6 @@ export const SELECTABLE_WORKFLOW_SKILLS = [
|
|
|
234
296
|
codex: '.agents/skills/ux-expert/SKILL.md',
|
|
235
297
|
gemini: '.agents/skills/ux-expert/SKILL.md',
|
|
236
298
|
claude: '.agents/skills/ux-expert/SKILL.md',
|
|
237
|
-
windsurf: '.agents/skills/ux-expert/SKILL.md',
|
|
238
299
|
},
|
|
239
300
|
},
|
|
240
301
|
{
|
|
@@ -247,7 +308,6 @@ export const SELECTABLE_WORKFLOW_SKILLS = [
|
|
|
247
308
|
codex: '.agents/skills/export-to-github/SKILL.md',
|
|
248
309
|
gemini: '.agents/skills/export-to-github/SKILL.md',
|
|
249
310
|
claude: '.agents/skills/export-to-github/SKILL.md',
|
|
250
|
-
windsurf: '.agents/skills/export-to-github/SKILL.md',
|
|
251
311
|
},
|
|
252
312
|
supplementalTargetsByAgent: {
|
|
253
313
|
codex: [
|
|
@@ -280,7 +340,6 @@ export const SELECTABLE_WORKFLOW_SKILLS = [
|
|
|
280
340
|
codex: '.agents/skills/export-to-notion/SKILL.md',
|
|
281
341
|
gemini: '.agents/skills/export-to-notion/SKILL.md',
|
|
282
342
|
claude: '.agents/skills/export-to-notion/SKILL.md',
|
|
283
|
-
windsurf: '.agents/skills/export-to-notion/SKILL.md',
|
|
284
343
|
},
|
|
285
344
|
supplementalTargetsByAgent: {
|
|
286
345
|
codex: [
|
|
@@ -352,6 +411,7 @@ export const SUPPORTED_AGENTS = [
|
|
|
352
411
|
description: 'Create .codex/config.toml pointing Codex to AGENTS.md',
|
|
353
412
|
targetRelativePath: '.codex/config.toml',
|
|
354
413
|
templateRelativePath: '.codex/config.toml',
|
|
414
|
+
supportsForegroundWorkers: true,
|
|
355
415
|
},
|
|
356
416
|
{
|
|
357
417
|
id: 'gemini',
|
|
@@ -359,6 +419,7 @@ export const SUPPORTED_AGENTS = [
|
|
|
359
419
|
description: 'Create GEMINI.md that delegates to AGENTS.md',
|
|
360
420
|
targetRelativePath: 'GEMINI.md',
|
|
361
421
|
templateRelativePath: 'GEMINI.md',
|
|
422
|
+
supportsForegroundWorkers: true,
|
|
362
423
|
},
|
|
363
424
|
{
|
|
364
425
|
id: 'claude',
|
|
@@ -366,11 +427,7 @@ export const SUPPORTED_AGENTS = [
|
|
|
366
427
|
description: 'Create CLAUDE.md that delegates to AGENTS.md',
|
|
367
428
|
targetRelativePath: 'CLAUDE.md',
|
|
368
429
|
templateRelativePath: 'CLAUDE.md',
|
|
369
|
-
|
|
370
|
-
{
|
|
371
|
-
id: 'windsurf',
|
|
372
|
-
name: 'Windsurf',
|
|
373
|
-
description: 'Use root AGENTS.md and shared .agents/skills/ discovery',
|
|
430
|
+
supportsForegroundWorkers: true,
|
|
374
431
|
},
|
|
375
432
|
];
|
|
376
433
|
export function resolveSelectableMcpServerById(serverId) {
|
|
@@ -1,2 +1,3 @@
|
|
|
1
|
+
export { extractProjectOverview, getTemplateVersion, readTemplate, readTemplateManifest, renderMissingWorkflowFiles, renderSkillRouting, renderTemplateForSync, renderWorkerToolboxRouting, renderWorkerToolboxRoutingPlaceholders, } from './templates.js';
|
|
1
2
|
export { MANDATORY_SKILLS, SELECTABLE_ARCHITECTURE_SKILLS, SELECTABLE_DATABASE_SKILLS, SELECTABLE_FRAMEWORK_SKILLS, SELECTABLE_LANGUAGE_SKILLS, SELECTABLE_MCP_SERVERS, SELECTABLE_WORKFLOW_SKILLS, SESSION_START_HOOKS, SUPPORTED_AGENTS, getMcpServersRequiredByWorkflowSkills, getWorkflowSkillsImpliedByMcpServers, resolveSelectableMcpServerById, resolveSelectableSkillById, } from './catalog.js';
|
|
2
|
-
export { getSelectedAgentsFromState, getSelectedArchitectureSkillFromState, getSelectedDatabaseSkillsFromState, getSelectedFrameworkSkillsFromState, getSelectedLanguageSkillsFromState, getSelectedMcpServersFromState,
|
|
3
|
+
export { getSelectedAgentsFromState, getSelectedArchitectureSkillFromState, getSelectedDatabaseSkillsFromState, getSelectedFrameworkSkillsFromState, getSelectedLanguageSkillsFromState, getSelectedMcpServersFromState, getSelectedSkillTargetsForAgents, getSelectedWorkflowSkillsFromState, getSkillTargetsForAgents, getWorkflowTargets, } from '../../support/expected-workflow-targets.js';
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { getTemplatesPath } from '../../shared/paths.js';
|
|
4
|
+
import { renderMcpConfig, resolveMcpConfigAgentId } from '../agent-tool-configuration/index.js';
|
|
5
|
+
export function readTemplate(relativePath) {
|
|
6
|
+
return fs.readFileSync(path.join(getTemplatesPath(), relativePath), 'utf8');
|
|
7
|
+
}
|
|
8
|
+
export function readTemplateManifest() {
|
|
9
|
+
const manifest = JSON.parse(fs.readFileSync(path.join(getTemplatesPath(), 'manifest.json'), 'utf8'));
|
|
10
|
+
if (!isTemplateManifest(manifest)) {
|
|
11
|
+
throw new Error('templates/manifest.json is not a valid template manifest.');
|
|
12
|
+
}
|
|
13
|
+
return manifest;
|
|
14
|
+
}
|
|
15
|
+
export function getTemplateVersion(manifest, templateRelativePath) {
|
|
16
|
+
const template = manifest.templates[templateRelativePath];
|
|
17
|
+
if (!template) {
|
|
18
|
+
throw new Error(`Template ${templateRelativePath} is missing from templates/manifest.json.`);
|
|
19
|
+
}
|
|
20
|
+
return template.version;
|
|
21
|
+
}
|
|
22
|
+
function isTemplateManifest(value) {
|
|
23
|
+
if (!value || typeof value !== 'object') {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
const manifest = value;
|
|
27
|
+
return (typeof manifest.templateVersion === 'string' &&
|
|
28
|
+
!!manifest.templates &&
|
|
29
|
+
typeof manifest.templates === 'object' &&
|
|
30
|
+
Object.values(manifest.templates).every((template) => !!template &&
|
|
31
|
+
typeof template === 'object' &&
|
|
32
|
+
typeof template.version === 'string' &&
|
|
33
|
+
typeof template.description === 'string' &&
|
|
34
|
+
Array.isArray(template.changes) &&
|
|
35
|
+
template.changes.every((change) => typeof change === 'string')));
|
|
36
|
+
}
|
|
37
|
+
export function renderTemplateForSync({ templateRelativePath, currentPath, selectedLanguageSkills, selectedFrameworkSkills, selectedArchitectureSkill, selectedWorkflowSkills = [], selectedDatabaseSkills = [], selectedMcpServers = [], }) {
|
|
38
|
+
let contents = readTemplate(templateRelativePath);
|
|
39
|
+
const mcpConfigAgentId = resolveMcpConfigAgentId(templateRelativePath);
|
|
40
|
+
if (mcpConfigAgentId) {
|
|
41
|
+
return renderMcpConfig({ agentId: mcpConfigAgentId, baseContents: contents, selectedMcpServers });
|
|
42
|
+
}
|
|
43
|
+
if (contents.includes('{{PROJECT_OVERVIEW}}')) {
|
|
44
|
+
contents = contents.replace('{{PROJECT_OVERVIEW}}', extractProjectOverview(currentPath) ?? 'Describe this project.');
|
|
45
|
+
}
|
|
46
|
+
contents = renderSkillRouting(contents, selectedLanguageSkills, selectedFrameworkSkills, selectedArchitectureSkill, selectedWorkflowSkills, selectedDatabaseSkills);
|
|
47
|
+
contents = renderWorkerToolboxRoutingPlaceholders(contents, selectedLanguageSkills, selectedFrameworkSkills, selectedArchitectureSkill, selectedWorkflowSkills, selectedDatabaseSkills);
|
|
48
|
+
return contents;
|
|
49
|
+
}
|
|
50
|
+
export function renderMissingWorkflowFiles({ missingTargets, overview, selectedLanguageSkills, selectedFrameworkSkills, selectedArchitectureSkill, selectedWorkflowSkills = [], selectedDatabaseSkills = [], selectedMcpServers = [], }) {
|
|
51
|
+
return missingTargets.map((target) => {
|
|
52
|
+
let contents = readTemplate(target.templateRelativePath);
|
|
53
|
+
if (target.mcpConfigAgentId && (target.selectedMcpServers?.length || selectedMcpServers.length)) {
|
|
54
|
+
contents = renderMcpConfig({
|
|
55
|
+
agentId: target.mcpConfigAgentId,
|
|
56
|
+
baseContents: contents,
|
|
57
|
+
selectedMcpServers: target.selectedMcpServers ?? selectedMcpServers,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
if (target.requiresProjectOverview) {
|
|
61
|
+
if (!overview?.trim()) {
|
|
62
|
+
throw new Error('Project overview is required to create AGENTS.md.');
|
|
63
|
+
}
|
|
64
|
+
contents = contents.replace('{{PROJECT_OVERVIEW}}', overview.trim());
|
|
65
|
+
}
|
|
66
|
+
contents = renderSkillRouting(contents, selectedLanguageSkills, selectedFrameworkSkills, selectedArchitectureSkill, selectedWorkflowSkills, selectedDatabaseSkills);
|
|
67
|
+
contents = renderWorkerToolboxRoutingPlaceholders(contents, selectedLanguageSkills, selectedFrameworkSkills, selectedArchitectureSkill, selectedWorkflowSkills, selectedDatabaseSkills);
|
|
68
|
+
return {
|
|
69
|
+
label: target.label,
|
|
70
|
+
targetPath: target.targetPath,
|
|
71
|
+
contents,
|
|
72
|
+
};
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
export function renderSkillRouting(contents, selectedLanguageSkills, selectedFrameworkSkills, selectedArchitectureSkill, selectedWorkflowSkills = [], selectedDatabaseSkills = []) {
|
|
76
|
+
if (!contents.includes('{{OPTIONAL_SKILL_ROUTING}}')) {
|
|
77
|
+
return contents;
|
|
78
|
+
}
|
|
79
|
+
const optionalRouting = [...selectedLanguageSkills, ...selectedFrameworkSkills, ...selectedDatabaseSkills, ...(selectedArchitectureSkill ? [selectedArchitectureSkill] : []), ...selectedWorkflowSkills]
|
|
80
|
+
.map((skill) => `- ${skill.routingInstruction}`)
|
|
81
|
+
.join('\n');
|
|
82
|
+
return contents.replace('{{OPTIONAL_SKILL_ROUTING}}', optionalRouting);
|
|
83
|
+
}
|
|
84
|
+
export function renderWorkerToolboxRouting({ profile, selectedLanguageSkills, selectedFrameworkSkills, selectedArchitectureSkill, selectedWorkflowSkills = [], selectedDatabaseSkills = [], }) {
|
|
85
|
+
const selectedSkills = collectWorkerRelevantSkills({
|
|
86
|
+
selectedLanguageSkills,
|
|
87
|
+
selectedFrameworkSkills,
|
|
88
|
+
selectedArchitectureSkill,
|
|
89
|
+
selectedWorkflowSkills,
|
|
90
|
+
selectedDatabaseSkills,
|
|
91
|
+
});
|
|
92
|
+
const selectedSkillLines = selectedSkills.map((skill) => `- ${skill.name}: read \`${getSharedSkillTargetPath(skill)}\` when relevant. ${skill.routingInstruction}`);
|
|
93
|
+
const selectedSkillsSection = selectedSkillLines.length > 0
|
|
94
|
+
? selectedSkillLines.join('\n')
|
|
95
|
+
: '- No optional implementation-relevant Sibu skills are selected for this project. Use source artifacts and flag unmapped patterns as risks instead of guessing silently.';
|
|
96
|
+
return `## Focused ${profile} worker routing
|
|
97
|
+
|
|
98
|
+
- Always read and apply \`.agents/skills/clean-code/SKILL.md\` before ${profile === 'planner' ? 'writing implementation plan steps' : 'editing code or running story execution'}.
|
|
99
|
+
- Read the worker toolbox skill path provided in the main-agent packet before doing work.
|
|
100
|
+
- Read every required skill path listed in the packet. If a required skill path is missing, stop and report the blocker to the main agent.
|
|
101
|
+
- Read optional installed skill paths only when they are relevant to the story, touched files, source artifacts, or validation work.
|
|
102
|
+
- Treat distilled skill constraints from the packet as binding task constraints.
|
|
103
|
+
- If an optional relevant skill is not installed and you encounter an unmapped language, framework, database, or architecture pattern, do not guess silently; continue only when safe and flag the gap as a ${profile === 'planner' ? 'plan risk' : 'Review Gate risk'}.
|
|
104
|
+
|
|
105
|
+
### Optional installed skills relevant to ${profile} work
|
|
106
|
+
${selectedSkillsSection}`;
|
|
107
|
+
}
|
|
108
|
+
export function renderWorkerToolboxRoutingPlaceholders(contents, selectedLanguageSkills, selectedFrameworkSkills, selectedArchitectureSkill, selectedWorkflowSkills = [], selectedDatabaseSkills = []) {
|
|
109
|
+
const placeholderProfiles = [
|
|
110
|
+
{ placeholder: '{{PLANNER_WORKER_ROUTING}}', profile: 'planner' },
|
|
111
|
+
{ placeholder: '{{EXECUTOR_WORKER_ROUTING}}', profile: 'executor' },
|
|
112
|
+
];
|
|
113
|
+
let renderedContents = contents;
|
|
114
|
+
for (const { placeholder, profile } of placeholderProfiles) {
|
|
115
|
+
if (!renderedContents.includes(placeholder)) {
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
renderedContents = renderedContents.replace(placeholder, renderWorkerToolboxRouting({
|
|
119
|
+
profile,
|
|
120
|
+
selectedLanguageSkills,
|
|
121
|
+
selectedFrameworkSkills,
|
|
122
|
+
selectedArchitectureSkill,
|
|
123
|
+
selectedWorkflowSkills,
|
|
124
|
+
selectedDatabaseSkills,
|
|
125
|
+
}));
|
|
126
|
+
}
|
|
127
|
+
return renderedContents;
|
|
128
|
+
}
|
|
129
|
+
function collectWorkerRelevantSkills({ selectedLanguageSkills, selectedFrameworkSkills, selectedArchitectureSkill, selectedWorkflowSkills, selectedDatabaseSkills, }) {
|
|
130
|
+
const implementationRelevantWorkflowSkills = selectedWorkflowSkills.filter((skill) => skill.id === 'ai-prompt-engineer-master' || skill.id === 'ux-expert');
|
|
131
|
+
return [
|
|
132
|
+
...selectedLanguageSkills,
|
|
133
|
+
...selectedFrameworkSkills,
|
|
134
|
+
...selectedDatabaseSkills,
|
|
135
|
+
...(selectedArchitectureSkill ? [selectedArchitectureSkill] : []),
|
|
136
|
+
...implementationRelevantWorkflowSkills,
|
|
137
|
+
];
|
|
138
|
+
}
|
|
139
|
+
function getSharedSkillTargetPath(skill) {
|
|
140
|
+
const sharedTargetPath = Object.values(skill.targetRelativePathsByAgent).find((targetPath) => targetPath !== undefined);
|
|
141
|
+
if (!sharedTargetPath) {
|
|
142
|
+
throw new Error(`Selectable skill ${skill.id} has no target path.`);
|
|
143
|
+
}
|
|
144
|
+
return sharedTargetPath;
|
|
145
|
+
}
|
|
146
|
+
export function extractProjectOverview(filePath) {
|
|
147
|
+
if (!fs.existsSync(filePath)) {
|
|
148
|
+
return undefined;
|
|
149
|
+
}
|
|
150
|
+
const contents = fs.readFileSync(filePath, 'utf8');
|
|
151
|
+
const match = contents.match(/## Project overview\s+([\s\S]*?)(?=\n## |$)/);
|
|
152
|
+
const overview = match?.[1]?.trim();
|
|
153
|
+
return overview || undefined;
|
|
154
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { handleListSkills } from './list-skills/handler.js';
|
|
2
|
+
export { getNextSkillSelection, handleUseSkill } from './use-skill/handler.js';
|
|
3
|
+
export { handleStopManagingFile, stopSelectedSkill } from './stop-managing-file/handler.js';
|
|
4
|
+
export { getMcpServerListItems, handleListMcpServers } from './list-mcp-servers/handler.js';
|
|
5
|
+
export { getNextMcpSelection, handleUseMcpServer } from './use-mcp-server/handler.js';
|
|
6
|
+
export { applyStoppedMcpFileDeleteDecision, getNextStoppedMcpSelection, handleStopMcpServer, stopSelectedMcpServer } from './stop-mcp-server/handler.js';
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { intro, log, outro } from '@clack/prompts';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { SELECTABLE_MCP_SERVERS } from '../../template-catalog/index.js';
|
|
4
|
+
import { getProjectContext } from '../../../shared/paths.js';
|
|
5
|
+
import { renderIntro } from '../../../support/interactive-guidance/index.js';
|
|
6
|
+
import { readStateForDoctor } from '../../workflow-state-ledger/index.js';
|
|
7
|
+
const defaultDependencies = {
|
|
8
|
+
renderIntro,
|
|
9
|
+
intro,
|
|
10
|
+
logMessage: log.message,
|
|
11
|
+
logWarn: log.warn,
|
|
12
|
+
logInfo: log.info,
|
|
13
|
+
outro,
|
|
14
|
+
getStatePath: () => getProjectContext().statePath,
|
|
15
|
+
readState: readStateForDoctor,
|
|
16
|
+
};
|
|
17
|
+
export async function handleListMcpServers(_command, dependencies = defaultDependencies) {
|
|
18
|
+
await dependencies.renderIntro();
|
|
19
|
+
dependencies.intro(chalk.cyan('Available MCP servers'));
|
|
20
|
+
const statePath = dependencies.getStatePath();
|
|
21
|
+
const stateResult = dependencies.readState(statePath);
|
|
22
|
+
const state = stateResult.ok ? stateResult.state : undefined;
|
|
23
|
+
if (!stateResult.ok) {
|
|
24
|
+
dependencies.logWarn(`${stateResult.message} Showing available MCP servers without project state.`);
|
|
25
|
+
dependencies.logInfo('Run `sibu init` before selecting project MCP servers.');
|
|
26
|
+
}
|
|
27
|
+
dependencies.logInfo('Sibu configures MCP files only; prerequisites, credentials, and provider authentication remain user-owned.');
|
|
28
|
+
dependencies.logMessage(chalk.bold('MCP servers'));
|
|
29
|
+
for (const server of getMcpServerListItems(state)) {
|
|
30
|
+
const marker = server.selected ? chalk.green('● selected') : chalk.dim('○ available');
|
|
31
|
+
console.log(` ${marker} ${chalk.bold(server.name)} ${chalk.dim(`(${server.id})`)}`);
|
|
32
|
+
console.log(` ${chalk.dim(server.description)}`);
|
|
33
|
+
console.log(` ${chalk.dim(`Source: ${server.source}`)}`);
|
|
34
|
+
}
|
|
35
|
+
dependencies.outro(chalk.green('MCP server list ready.'));
|
|
36
|
+
}
|
|
37
|
+
export function getMcpServerListItems(state) {
|
|
38
|
+
const selectedServerIds = new Set(state?.selectedMcpServers ?? []);
|
|
39
|
+
return SELECTABLE_MCP_SERVERS.map((server) => ({
|
|
40
|
+
name: server.name,
|
|
41
|
+
id: server.id,
|
|
42
|
+
description: server.description,
|
|
43
|
+
source: server.source,
|
|
44
|
+
selected: selectedServerIds.has(server.id),
|
|
45
|
+
}));
|
|
46
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { intro, log, outro } from '@clack/prompts';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { SELECTABLE_ARCHITECTURE_SKILLS, SELECTABLE_DATABASE_SKILLS, SELECTABLE_FRAMEWORK_SKILLS, SELECTABLE_LANGUAGE_SKILLS, SELECTABLE_WORKFLOW_SKILLS } from '../../template-catalog/index.js';
|
|
4
|
+
import { getProjectContext } from '../../../shared/paths.js';
|
|
5
|
+
import { renderIntro } from '../../../support/interactive-guidance/index.js';
|
|
6
|
+
import { readStateForDoctor } from '../../workflow-state-ledger/index.js';
|
|
7
|
+
export async function handleListSkills(_command) {
|
|
8
|
+
await renderIntro();
|
|
9
|
+
intro(chalk.cyan('Available workflow skills'));
|
|
10
|
+
const { statePath } = getProjectContext();
|
|
11
|
+
const stateResult = readStateForDoctor(statePath);
|
|
12
|
+
const state = stateResult.ok ? stateResult.state : undefined;
|
|
13
|
+
if (!stateResult.ok) {
|
|
14
|
+
log.warn(`${stateResult.message} Showing available skills without project state.`);
|
|
15
|
+
log.info('Run `sibu init` before selecting project skills.');
|
|
16
|
+
}
|
|
17
|
+
logSkillGroup('Languages', getLanguageSkillItems(state));
|
|
18
|
+
logSkillGroup('Frameworks', getFrameworkSkillItems(state));
|
|
19
|
+
logSkillGroup('Databases', getDatabaseSkillItems(state));
|
|
20
|
+
logSkillGroup('Architecture', getArchitectureSkillItems(state));
|
|
21
|
+
logSkillGroup('Workflow', getWorkflowSkillItems(state));
|
|
22
|
+
outro(chalk.green('Skill list ready.'));
|
|
23
|
+
}
|
|
24
|
+
function getLanguageSkillItems(state) {
|
|
25
|
+
const selectedSkillIds = new Set(state?.selectedLanguageSkills ?? []);
|
|
26
|
+
return SELECTABLE_LANGUAGE_SKILLS.map((skill) => ({
|
|
27
|
+
name: skill.name,
|
|
28
|
+
id: skill.id,
|
|
29
|
+
description: skill.description,
|
|
30
|
+
selected: selectedSkillIds.has(skill.id),
|
|
31
|
+
}));
|
|
32
|
+
}
|
|
33
|
+
function getFrameworkSkillItems(state) {
|
|
34
|
+
const selectedSkillIds = new Set(state?.selectedFrameworkSkills ?? []);
|
|
35
|
+
return SELECTABLE_FRAMEWORK_SKILLS.map((skill) => ({
|
|
36
|
+
name: skill.name,
|
|
37
|
+
id: skill.id,
|
|
38
|
+
description: skill.description,
|
|
39
|
+
selected: selectedSkillIds.has(skill.id),
|
|
40
|
+
}));
|
|
41
|
+
}
|
|
42
|
+
function getDatabaseSkillItems(state) {
|
|
43
|
+
const selectedSkillIds = new Set(state?.selectedDatabaseSkills ?? []);
|
|
44
|
+
return SELECTABLE_DATABASE_SKILLS.map((skill) => ({
|
|
45
|
+
name: skill.name,
|
|
46
|
+
id: skill.id,
|
|
47
|
+
description: skill.description,
|
|
48
|
+
selected: selectedSkillIds.has(skill.id),
|
|
49
|
+
}));
|
|
50
|
+
}
|
|
51
|
+
function getArchitectureSkillItems(state) {
|
|
52
|
+
return SELECTABLE_ARCHITECTURE_SKILLS.map((skill) => ({
|
|
53
|
+
name: skill.name,
|
|
54
|
+
id: skill.id,
|
|
55
|
+
description: skill.description,
|
|
56
|
+
selected: state?.selectedArchitectureSkill === skill.id,
|
|
57
|
+
}));
|
|
58
|
+
}
|
|
59
|
+
function getWorkflowSkillItems(state) {
|
|
60
|
+
const selectedSkillIds = new Set(state?.selectedWorkflowSkills ?? []);
|
|
61
|
+
return SELECTABLE_WORKFLOW_SKILLS.map((skill) => ({
|
|
62
|
+
name: skill.name,
|
|
63
|
+
id: skill.id,
|
|
64
|
+
description: skill.description,
|
|
65
|
+
selected: selectedSkillIds.has(skill.id),
|
|
66
|
+
}));
|
|
67
|
+
}
|
|
68
|
+
function logSkillGroup(label, skills) {
|
|
69
|
+
log.message(chalk.bold(label));
|
|
70
|
+
for (const skill of skills) {
|
|
71
|
+
const marker = skill.selected ? chalk.green('● selected') : chalk.dim('○ available');
|
|
72
|
+
console.log(` ${marker} ${chalk.bold(skill.name)} ${chalk.dim(`(${skill.id})`)}`);
|
|
73
|
+
console.log(` ${chalk.dim(skill.description)}`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|