@juancr11/sibu 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/features/list-skills/handler.js +11 -1
- package/bin/features/stop-managing-file/handler.js +7 -1
- package/bin/features/sync-project/apply-action.js +3 -1
- package/bin/features/use-skill/handler.js +32 -2
- package/bin/shared/catalog.js +32 -0
- package/bin/shared/state.js +2 -0
- package/bin/shared/sync-preview.js +8 -4
- package/bin/shared/templates.js +4 -4
- package/bin/shared/workflow-targets.js +12 -7
- package/package.json +1 -1
- package/templates/manifest.json +24 -14
- package/templates/skills/ai-implementation-plan-executor/SKILL.md +5 -0
- package/templates/skills/ai-implementation-planner/SKILL.md +5 -0
- package/templates/skills/ai-prompt-engineer-master/SKILL.md +98 -0
- package/templates/skills/scrum-master-planner/SKILL.md +5 -0
- package/templates/skills/technical-design-writer/SKILL.md +9 -4
- package/templates/skills/ux-expert/SKILL.md +93 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { intro, log, outro } from '@clack/prompts';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
|
-
import { SELECTABLE_ARCHITECTURE_SKILLS, SELECTABLE_FRAMEWORK_SKILLS, SELECTABLE_LANGUAGE_SKILLS } from '../../shared/catalog.js';
|
|
3
|
+
import { SELECTABLE_ARCHITECTURE_SKILLS, SELECTABLE_FRAMEWORK_SKILLS, SELECTABLE_LANGUAGE_SKILLS, SELECTABLE_WORKFLOW_SKILLS } from '../../shared/catalog.js';
|
|
4
4
|
import { getProjectContext } from '../../shared/paths.js';
|
|
5
5
|
import { renderIntro } from '../../shared/prompts.js';
|
|
6
6
|
import { readStateForDoctor } from '../../shared/state.js';
|
|
@@ -17,6 +17,7 @@ export async function handleListSkills(_command) {
|
|
|
17
17
|
logSkillGroup('Languages', getLanguageSkillItems(state));
|
|
18
18
|
logSkillGroup('Frameworks', getFrameworkSkillItems(state));
|
|
19
19
|
logSkillGroup('Architecture', getArchitectureSkillItems(state));
|
|
20
|
+
logSkillGroup('Workflow', getWorkflowSkillItems(state));
|
|
20
21
|
outro(chalk.green('Skill list ready.'));
|
|
21
22
|
}
|
|
22
23
|
function getLanguageSkillItems(state) {
|
|
@@ -45,6 +46,15 @@ function getArchitectureSkillItems(state) {
|
|
|
45
46
|
selected: state?.selectedArchitectureSkill === skill.id,
|
|
46
47
|
}));
|
|
47
48
|
}
|
|
49
|
+
function getWorkflowSkillItems(state) {
|
|
50
|
+
const selectedSkillIds = new Set(state?.selectedWorkflowSkills ?? []);
|
|
51
|
+
return SELECTABLE_WORKFLOW_SKILLS.map((skill) => ({
|
|
52
|
+
name: skill.name,
|
|
53
|
+
id: skill.id,
|
|
54
|
+
description: skill.description,
|
|
55
|
+
selected: selectedSkillIds.has(skill.id),
|
|
56
|
+
}));
|
|
57
|
+
}
|
|
48
58
|
function logSkillGroup(label, skills) {
|
|
49
59
|
log.message(chalk.bold(label));
|
|
50
60
|
for (const skill of skills) {
|
|
@@ -9,7 +9,7 @@ import { renderIntro } from '../../shared/prompts.js';
|
|
|
9
9
|
import { cloneState, readStateForDoctor, writeStateFile } from '../../shared/state.js';
|
|
10
10
|
import { getTemplateVersion, readTemplateManifest, renderTemplateForSync } from '../../shared/templates.js';
|
|
11
11
|
import { removeUndefinedFields } from '../../shared/object.js';
|
|
12
|
-
import { getSelectedAgentsFromState, getSelectedArchitectureSkillFromState, getSelectedFrameworkSkillsFromState, getSelectedLanguageSkillsFromState, } from '../../shared/workflow-targets.js';
|
|
12
|
+
import { getSelectedAgentsFromState, getSelectedArchitectureSkillFromState, getSelectedFrameworkSkillsFromState, getSelectedLanguageSkillsFromState, getSelectedWorkflowSkillsFromState, } from '../../shared/workflow-targets.js';
|
|
13
13
|
export async function handleStopManagingFile({ skillName }) {
|
|
14
14
|
await renderIntro();
|
|
15
15
|
intro(chalk.cyan('Updating skill management'));
|
|
@@ -109,6 +109,8 @@ function isSkillSelected(state, resolved) {
|
|
|
109
109
|
return state.selectedFrameworkSkills?.includes(resolved.skill.id) ?? false;
|
|
110
110
|
case 'architecture':
|
|
111
111
|
return state.selectedArchitectureSkill === resolved.skill.id;
|
|
112
|
+
case 'workflow':
|
|
113
|
+
return state.selectedWorkflowSkills?.includes(resolved.skill.id) ?? false;
|
|
112
114
|
}
|
|
113
115
|
}
|
|
114
116
|
function removeSelectedSkill(state, resolved) {
|
|
@@ -122,6 +124,9 @@ function removeSelectedSkill(state, resolved) {
|
|
|
122
124
|
case 'architecture':
|
|
123
125
|
delete state.selectedArchitectureSkill;
|
|
124
126
|
return;
|
|
127
|
+
case 'workflow':
|
|
128
|
+
state.selectedWorkflowSkills = (state.selectedWorkflowSkills ?? []).filter((skillId) => skillId !== resolved.skill.id);
|
|
129
|
+
return;
|
|
125
130
|
}
|
|
126
131
|
}
|
|
127
132
|
function getSkillManagedPaths(rootPath, state, resolved) {
|
|
@@ -161,6 +166,7 @@ function getAgentsUpdate(rootPath, state) {
|
|
|
161
166
|
selectedLanguageSkills: getSelectedLanguageSkillsFromState(state),
|
|
162
167
|
selectedFrameworkSkills: getSelectedFrameworkSkillsFromState(state),
|
|
163
168
|
selectedArchitectureSkill: getSelectedArchitectureSkillFromState(state),
|
|
169
|
+
selectedWorkflowSkills: getSelectedWorkflowSkillsFromState(state),
|
|
164
170
|
}),
|
|
165
171
|
};
|
|
166
172
|
}
|
|
@@ -5,7 +5,7 @@ import { sha256 } from '../../shared/hash.js';
|
|
|
5
5
|
import { getSideTemplatePath } from '../../shared/paths.js';
|
|
6
6
|
import { cloneState } from '../../shared/state.js';
|
|
7
7
|
import { getTemplateVersion, renderTemplateForSync } from '../../shared/templates.js';
|
|
8
|
-
import { getSelectedArchitectureSkillFromState, getSelectedFrameworkSkillsFromState, getSelectedLanguageSkillsFromState } from '../../shared/workflow-targets.js';
|
|
8
|
+
import { getSelectedArchitectureSkillFromState, getSelectedFrameworkSkillsFromState, getSelectedLanguageSkillsFromState, getSelectedWorkflowSkillsFromState, } from '../../shared/workflow-targets.js';
|
|
9
9
|
export function applySyncAction({ rootPath, state, manifest, preview, action, }) {
|
|
10
10
|
const nextState = cloneState(state);
|
|
11
11
|
const managedFile = nextState.managedFiles[preview.relativePath] ?? preview.managedFile;
|
|
@@ -19,6 +19,7 @@ export function applySyncAction({ rootPath, state, manifest, preview, action, })
|
|
|
19
19
|
selectedLanguageSkills: getSelectedLanguageSkillsFromState(nextState),
|
|
20
20
|
selectedFrameworkSkills: getSelectedFrameworkSkillsFromState(nextState),
|
|
21
21
|
selectedArchitectureSkill: getSelectedArchitectureSkillFromState(nextState),
|
|
22
|
+
selectedWorkflowSkills: getSelectedWorkflowSkillsFromState(nextState),
|
|
22
23
|
});
|
|
23
24
|
fs.mkdirSync(path.dirname(targetPath), { recursive: true });
|
|
24
25
|
fs.writeFileSync(targetPath, contents, 'utf8');
|
|
@@ -54,6 +55,7 @@ export function applySyncAction({ rootPath, state, manifest, preview, action, })
|
|
|
54
55
|
selectedLanguageSkills: getSelectedLanguageSkillsFromState(state),
|
|
55
56
|
selectedFrameworkSkills: getSelectedFrameworkSkillsFromState(state),
|
|
56
57
|
selectedArchitectureSkill: getSelectedArchitectureSkillFromState(state),
|
|
58
|
+
selectedWorkflowSkills: getSelectedWorkflowSkillsFromState(state),
|
|
57
59
|
});
|
|
58
60
|
fs.mkdirSync(path.dirname(sideTemplatePath), { recursive: true });
|
|
59
61
|
fs.writeFileSync(sideTemplatePath, contents, 'utf8');
|
|
@@ -44,6 +44,7 @@ export function getNextSkillSelection(state, skillName) {
|
|
|
44
44
|
}
|
|
45
45
|
const selectedLanguageSkills = [...(state.selectedLanguageSkills ?? [])];
|
|
46
46
|
const selectedFrameworkSkills = [...(state.selectedFrameworkSkills ?? [])];
|
|
47
|
+
const selectedWorkflowSkills = [...(state.selectedWorkflowSkills ?? [])];
|
|
47
48
|
switch (resolution.resolved.kind) {
|
|
48
49
|
case 'language':
|
|
49
50
|
if (selectedLanguageSkills.includes(resolution.resolved.skill.id)) {
|
|
@@ -56,6 +57,7 @@ export function getNextSkillSelection(state, skillName) {
|
|
|
56
57
|
selectedLanguageSkills: [...selectedLanguageSkills, resolution.resolved.skill.id].map(getLanguageSkillById),
|
|
57
58
|
selectedFrameworkSkills: selectedFrameworkSkills.map(getFrameworkSkillById),
|
|
58
59
|
selectedArchitectureSkill: getArchitectureSkillById(state.selectedArchitectureSkill),
|
|
60
|
+
selectedWorkflowSkills: selectedWorkflowSkills.map(getWorkflowSkillById),
|
|
59
61
|
},
|
|
60
62
|
};
|
|
61
63
|
case 'framework':
|
|
@@ -69,6 +71,7 @@ export function getNextSkillSelection(state, skillName) {
|
|
|
69
71
|
selectedLanguageSkills: selectedLanguageSkills.map(getLanguageSkillById),
|
|
70
72
|
selectedFrameworkSkills: [...selectedFrameworkSkills, resolution.resolved.skill.id].map(getFrameworkSkillById),
|
|
71
73
|
selectedArchitectureSkill: getArchitectureSkillById(state.selectedArchitectureSkill),
|
|
74
|
+
selectedWorkflowSkills: selectedWorkflowSkills.map(getWorkflowSkillById),
|
|
72
75
|
},
|
|
73
76
|
};
|
|
74
77
|
case 'architecture':
|
|
@@ -89,6 +92,21 @@ export function getNextSkillSelection(state, skillName) {
|
|
|
89
92
|
selectedLanguageSkills: selectedLanguageSkills.map(getLanguageSkillById),
|
|
90
93
|
selectedFrameworkSkills: selectedFrameworkSkills.map(getFrameworkSkillById),
|
|
91
94
|
selectedArchitectureSkill: resolution.resolved.skill,
|
|
95
|
+
selectedWorkflowSkills: selectedWorkflowSkills.map(getWorkflowSkillById),
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
case 'workflow':
|
|
99
|
+
if (selectedWorkflowSkills.includes(resolution.resolved.skill.id)) {
|
|
100
|
+
return { status: 'noop', message: `${resolution.resolved.skill.name} is already selected.` };
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
status: 'selected',
|
|
104
|
+
skillName: resolution.resolved.skill.name,
|
|
105
|
+
selection: {
|
|
106
|
+
selectedLanguageSkills: selectedLanguageSkills.map(getLanguageSkillById),
|
|
107
|
+
selectedFrameworkSkills: selectedFrameworkSkills.map(getFrameworkSkillById),
|
|
108
|
+
selectedArchitectureSkill: getArchitectureSkillById(state.selectedArchitectureSkill),
|
|
109
|
+
selectedWorkflowSkills: [...selectedWorkflowSkills, resolution.resolved.skill.id].map(getWorkflowSkillById),
|
|
92
110
|
},
|
|
93
111
|
};
|
|
94
112
|
}
|
|
@@ -108,6 +126,7 @@ function applySelectedSkill({ rootPath, statePath, state, selectionResult, }) {
|
|
|
108
126
|
selectedLanguageSkills: selectionResult.selection.selectedLanguageSkills,
|
|
109
127
|
selectedFrameworkSkills: selectionResult.selection.selectedFrameworkSkills,
|
|
110
128
|
selectedArchitectureSkill: selectionResult.selection.selectedArchitectureSkill,
|
|
129
|
+
selectedWorkflowSkills: selectionResult.selection.selectedWorkflowSkills,
|
|
111
130
|
});
|
|
112
131
|
const [newSkillFile] = renderMissingWorkflowFiles({
|
|
113
132
|
missingTargets: [plan.newSkillTarget],
|
|
@@ -127,6 +146,7 @@ function applySelectedSkill({ rootPath, statePath, state, selectionResult, }) {
|
|
|
127
146
|
selectedLanguageSkills: selectionResult.selection.selectedLanguageSkills,
|
|
128
147
|
selectedFrameworkSkills: selectionResult.selection.selectedFrameworkSkills,
|
|
129
148
|
selectedArchitectureSkill: selectionResult.selection.selectedArchitectureSkill,
|
|
149
|
+
selectedWorkflowSkills: selectionResult.selection.selectedWorkflowSkills,
|
|
130
150
|
targets: plan.targets,
|
|
131
151
|
});
|
|
132
152
|
log.success(`Updated ${STATE_RELATIVE_PATH}`);
|
|
@@ -134,8 +154,8 @@ function applySelectedSkill({ rootPath, statePath, state, selectionResult, }) {
|
|
|
134
154
|
}
|
|
135
155
|
function buildSkillApplicationPlan({ rootPath, state, selectionResult, }) {
|
|
136
156
|
const selectedAgents = getSelectedAgentsFromState(state);
|
|
137
|
-
const previousTargets = getWorkflowTargets(rootPath, selectedAgents, getSelectedLanguageSkillsFromState(state), getSelectedFrameworkSkillsFromState(state), getArchitectureSkillById(state.selectedArchitectureSkill));
|
|
138
|
-
const targets = getWorkflowTargets(rootPath, selectedAgents, selectionResult.selection.selectedLanguageSkills, selectionResult.selection.selectedFrameworkSkills, selectionResult.selection.selectedArchitectureSkill);
|
|
157
|
+
const previousTargets = getWorkflowTargets(rootPath, selectedAgents, getSelectedLanguageSkillsFromState(state), getSelectedFrameworkSkillsFromState(state), getArchitectureSkillById(state.selectedArchitectureSkill), getSelectedWorkflowSkillsFromState(state));
|
|
158
|
+
const targets = getWorkflowTargets(rootPath, selectedAgents, selectionResult.selection.selectedLanguageSkills, selectionResult.selection.selectedFrameworkSkills, selectionResult.selection.selectedArchitectureSkill, selectionResult.selection.selectedWorkflowSkills);
|
|
139
159
|
const previousTargetPaths = new Set(previousTargets.map((target) => target.targetPath));
|
|
140
160
|
const newSkillTarget = targets.find((target) => !previousTargetPaths.has(target.targetPath));
|
|
141
161
|
const agentsTarget = targets.find((target) => target.label === 'AGENTS.md');
|
|
@@ -171,6 +191,9 @@ function getSelectedLanguageSkillsFromState(state) {
|
|
|
171
191
|
function getSelectedFrameworkSkillsFromState(state) {
|
|
172
192
|
return (state.selectedFrameworkSkills ?? []).map(getFrameworkSkillById);
|
|
173
193
|
}
|
|
194
|
+
function getSelectedWorkflowSkillsFromState(state) {
|
|
195
|
+
return (state.selectedWorkflowSkills ?? []).map(getWorkflowSkillById);
|
|
196
|
+
}
|
|
174
197
|
function getLanguageSkillById(skillId) {
|
|
175
198
|
const resolution = resolveSelectableSkillById(skillId);
|
|
176
199
|
if (!resolution.ok || resolution.resolved.kind !== 'language') {
|
|
@@ -195,3 +218,10 @@ function getArchitectureSkillById(skillId) {
|
|
|
195
218
|
}
|
|
196
219
|
return resolution.resolved.skill;
|
|
197
220
|
}
|
|
221
|
+
function getWorkflowSkillById(skillId) {
|
|
222
|
+
const resolution = resolveSelectableSkillById(skillId);
|
|
223
|
+
if (!resolution.ok || resolution.resolved.kind !== 'workflow') {
|
|
224
|
+
throw new Error(`Unsupported workflow skill in state: ${skillId}`);
|
|
225
|
+
}
|
|
226
|
+
return resolution.resolved.skill;
|
|
227
|
+
}
|
package/bin/shared/catalog.js
CHANGED
|
@@ -154,6 +154,34 @@ export const SELECTABLE_ARCHITECTURE_SKILLS = [
|
|
|
154
154
|
},
|
|
155
155
|
},
|
|
156
156
|
];
|
|
157
|
+
export const SELECTABLE_WORKFLOW_SKILLS = [
|
|
158
|
+
{
|
|
159
|
+
id: 'ai-prompt-engineer-master',
|
|
160
|
+
name: 'AI Prompt Engineer Master',
|
|
161
|
+
description: 'Install guidance for creating, rewriting, optimizing, compressing, and evaluating AI prompts',
|
|
162
|
+
routingInstruction: 'For requests to create, rewrite, optimize, compress, evaluate, or systematize prompts for AI models, agents, tools, coding assistants, product workflows, or reusable prompt templates, use `ai-prompt-engineer-master`.',
|
|
163
|
+
templateRelativePath: 'skills/ai-prompt-engineer-master/SKILL.md',
|
|
164
|
+
targetRelativePathsByAgent: {
|
|
165
|
+
codex: '.agents/skills/ai-prompt-engineer-master/SKILL.md',
|
|
166
|
+
gemini: '.agents/skills/ai-prompt-engineer-master/SKILL.md',
|
|
167
|
+
claude: '.agents/skills/ai-prompt-engineer-master/SKILL.md',
|
|
168
|
+
windsurf: '.agents/skills/ai-prompt-engineer-master/SKILL.md',
|
|
169
|
+
},
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
id: 'ux-expert',
|
|
173
|
+
name: 'UX Expert',
|
|
174
|
+
description: 'Install senior UX/UI guidance for UI-changing features, responsive layouts, flows, states, accessibility, and binding mockups',
|
|
175
|
+
routingInstruction: 'For UX/UI design after product definition when a feature has UI changes, use `ux-expert`; downstream technical design, Scrum planning, implementation planning, and implementation must treat mockups in `docs/features/<feature-slug>/ux.md` as binding UI goals, not redesign targets.',
|
|
176
|
+
templateRelativePath: 'skills/ux-expert/SKILL.md',
|
|
177
|
+
targetRelativePathsByAgent: {
|
|
178
|
+
codex: '.agents/skills/ux-expert/SKILL.md',
|
|
179
|
+
gemini: '.agents/skills/ux-expert/SKILL.md',
|
|
180
|
+
claude: '.agents/skills/ux-expert/SKILL.md',
|
|
181
|
+
windsurf: '.agents/skills/ux-expert/SKILL.md',
|
|
182
|
+
},
|
|
183
|
+
},
|
|
184
|
+
];
|
|
157
185
|
export const SUPPORTED_AGENTS = [
|
|
158
186
|
{
|
|
159
187
|
id: 'codex',
|
|
@@ -195,5 +223,9 @@ export function resolveSelectableSkillById(skillId) {
|
|
|
195
223
|
if (architectureSkill) {
|
|
196
224
|
return { ok: true, resolved: { kind: 'architecture', skill: architectureSkill } };
|
|
197
225
|
}
|
|
226
|
+
const workflowSkill = SELECTABLE_WORKFLOW_SKILLS.find((skill) => skill.id === skillId);
|
|
227
|
+
if (workflowSkill) {
|
|
228
|
+
return { ok: true, resolved: { kind: 'workflow', skill: workflowSkill } };
|
|
229
|
+
}
|
|
198
230
|
return { ok: false, message: `Unknown skill \`${skillId}\`. Run \`sibu skills list\` to see available skills.` };
|
|
199
231
|
}
|
package/bin/shared/state.js
CHANGED
|
@@ -55,6 +55,8 @@ function isSibuState(value) {
|
|
|
55
55
|
(state.selectedFrameworkSkills === undefined ||
|
|
56
56
|
(Array.isArray(state.selectedFrameworkSkills) && state.selectedFrameworkSkills.every((skill) => typeof skill === 'string'))) &&
|
|
57
57
|
(state.selectedArchitectureSkill === undefined || typeof state.selectedArchitectureSkill === 'string') &&
|
|
58
|
+
(state.selectedWorkflowSkills === undefined ||
|
|
59
|
+
(Array.isArray(state.selectedWorkflowSkills) && state.selectedWorkflowSkills.every((skill) => typeof skill === 'string'))) &&
|
|
58
60
|
(state.reviewedArchitectureSkills === undefined ||
|
|
59
61
|
(Array.isArray(state.reviewedArchitectureSkills) && state.reviewedArchitectureSkills.every((skill) => typeof skill === 'string'))) &&
|
|
60
62
|
!!state.managedFiles &&
|
|
@@ -3,7 +3,7 @@ import path from 'node:path';
|
|
|
3
3
|
import { sha256 } from './hash.js';
|
|
4
4
|
import { hasReviewedTemplateVersion } from './state.js';
|
|
5
5
|
import { renderTemplateForSync } from './templates.js';
|
|
6
|
-
import { getSelectedAgentsFromState, getSelectedArchitectureSkillFromState, getSelectedFrameworkSkillsFromState, getSelectedLanguageSkillsFromState, getWorkflowTargets, } from './workflow-targets.js';
|
|
6
|
+
import { getSelectedAgentsFromState, getSelectedArchitectureSkillFromState, getSelectedFrameworkSkillsFromState, getSelectedLanguageSkillsFromState, getSelectedWorkflowSkillsFromState, getWorkflowTargets, } from './workflow-targets.js';
|
|
7
7
|
const ACTIONABLE_SYNC_PREVIEW_STATUSES = new Set([
|
|
8
8
|
'new-template',
|
|
9
9
|
'missing',
|
|
@@ -29,6 +29,7 @@ export function getSyncPreviews({ rootPath, state, manifest }) {
|
|
|
29
29
|
const selectedLanguageSkills = getSelectedLanguageSkillsFromState(state);
|
|
30
30
|
const selectedFrameworkSkills = getSelectedFrameworkSkillsFromState(state);
|
|
31
31
|
const selectedArchitectureSkill = getSelectedArchitectureSkillFromState(state);
|
|
32
|
+
const selectedWorkflowSkills = getSelectedWorkflowSkillsFromState(state);
|
|
32
33
|
const previews = Object.entries(state.managedFiles).map(([relativePath, managedFile]) => getManagedFileSyncPreview({
|
|
33
34
|
rootPath,
|
|
34
35
|
manifest,
|
|
@@ -37,8 +38,9 @@ export function getSyncPreviews({ rootPath, state, manifest }) {
|
|
|
37
38
|
selectedLanguageSkills,
|
|
38
39
|
selectedFrameworkSkills,
|
|
39
40
|
selectedArchitectureSkill,
|
|
41
|
+
selectedWorkflowSkills,
|
|
40
42
|
}));
|
|
41
|
-
const expectedTargets = getWorkflowTargets(rootPath, getSelectedAgentsFromState(state), selectedLanguageSkills, selectedFrameworkSkills, selectedArchitectureSkill);
|
|
43
|
+
const expectedTargets = getWorkflowTargets(rootPath, getSelectedAgentsFromState(state), selectedLanguageSkills, selectedFrameworkSkills, selectedArchitectureSkill, selectedWorkflowSkills);
|
|
42
44
|
for (const target of expectedTargets) {
|
|
43
45
|
const relativePath = path.relative(rootPath, target.targetPath);
|
|
44
46
|
if (state.managedFiles[relativePath]) {
|
|
@@ -75,7 +77,7 @@ export function getSyncPreviews({ rootPath, state, manifest }) {
|
|
|
75
77
|
}
|
|
76
78
|
return previews;
|
|
77
79
|
}
|
|
78
|
-
function getManagedFileSyncPreview({ rootPath, manifest, relativePath, managedFile, selectedLanguageSkills, selectedFrameworkSkills, selectedArchitectureSkill, }) {
|
|
80
|
+
function getManagedFileSyncPreview({ rootPath, manifest, relativePath, managedFile, selectedLanguageSkills, selectedFrameworkSkills, selectedArchitectureSkill, selectedWorkflowSkills, }) {
|
|
79
81
|
if (managedFile.status === 'unmanaged') {
|
|
80
82
|
return { relativePath, managedFile, status: 'unmanaged', recordedTemplateVersion: managedFile.templateVersion, changes: [] };
|
|
81
83
|
}
|
|
@@ -94,6 +96,7 @@ function getManagedFileSyncPreview({ rootPath, manifest, relativePath, managedFi
|
|
|
94
96
|
selectedLanguageSkills,
|
|
95
97
|
selectedFrameworkSkills,
|
|
96
98
|
selectedArchitectureSkill,
|
|
99
|
+
selectedWorkflowSkills,
|
|
97
100
|
});
|
|
98
101
|
const hasUpdate = hasTemplateUpdate || hasSelectionUpdate;
|
|
99
102
|
const changes = hasTemplateUpdate ? template.changes : ['Refreshes generated skill routing for the current selected skills.'];
|
|
@@ -151,7 +154,7 @@ function getManagedFileSyncPreview({ rootPath, manifest, relativePath, managedFi
|
|
|
151
154
|
hasLocalFile,
|
|
152
155
|
};
|
|
153
156
|
}
|
|
154
|
-
function hasRenderedSelectionUpdate({ relativePath, currentPath, managedFile, selectedLanguageSkills, selectedFrameworkSkills, selectedArchitectureSkill, }) {
|
|
157
|
+
function hasRenderedSelectionUpdate({ relativePath, currentPath, managedFile, selectedLanguageSkills, selectedFrameworkSkills, selectedArchitectureSkill, selectedWorkflowSkills, }) {
|
|
155
158
|
if (relativePath !== 'AGENTS.md') {
|
|
156
159
|
return false;
|
|
157
160
|
}
|
|
@@ -161,6 +164,7 @@ function hasRenderedSelectionUpdate({ relativePath, currentPath, managedFile, se
|
|
|
161
164
|
selectedLanguageSkills,
|
|
162
165
|
selectedFrameworkSkills,
|
|
163
166
|
selectedArchitectureSkill,
|
|
167
|
+
selectedWorkflowSkills,
|
|
164
168
|
});
|
|
165
169
|
return sha256(renderedContents) !== managedFile.sha256;
|
|
166
170
|
}
|
package/bin/shared/templates.js
CHANGED
|
@@ -18,18 +18,18 @@ export function getTemplateVersion(manifest, templateRelativePath) {
|
|
|
18
18
|
}
|
|
19
19
|
return template.version;
|
|
20
20
|
}
|
|
21
|
-
export function renderTemplateForSync({ templateRelativePath, currentPath, selectedLanguageSkills, selectedFrameworkSkills, selectedArchitectureSkill, }) {
|
|
21
|
+
export function renderTemplateForSync({ templateRelativePath, currentPath, selectedLanguageSkills, selectedFrameworkSkills, selectedArchitectureSkill, selectedWorkflowSkills = [], }) {
|
|
22
22
|
let contents = readTemplate(templateRelativePath);
|
|
23
23
|
if (contents.includes('{{PROJECT_OVERVIEW}}')) {
|
|
24
24
|
contents = contents.replace('{{PROJECT_OVERVIEW}}', extractProjectOverview(currentPath) ?? 'Describe this project.');
|
|
25
25
|
}
|
|
26
|
-
return renderSkillRouting(contents, selectedLanguageSkills, selectedFrameworkSkills, selectedArchitectureSkill);
|
|
26
|
+
return renderSkillRouting(contents, selectedLanguageSkills, selectedFrameworkSkills, selectedArchitectureSkill, selectedWorkflowSkills);
|
|
27
27
|
}
|
|
28
|
-
export function renderSkillRouting(contents, selectedLanguageSkills, selectedFrameworkSkills, selectedArchitectureSkill) {
|
|
28
|
+
export function renderSkillRouting(contents, selectedLanguageSkills, selectedFrameworkSkills, selectedArchitectureSkill, selectedWorkflowSkills = []) {
|
|
29
29
|
if (!contents.includes('{{OPTIONAL_SKILL_ROUTING}}')) {
|
|
30
30
|
return contents;
|
|
31
31
|
}
|
|
32
|
-
const optionalRouting = [...selectedLanguageSkills, ...selectedFrameworkSkills, ...(selectedArchitectureSkill ? [selectedArchitectureSkill] : [])]
|
|
32
|
+
const optionalRouting = [...selectedLanguageSkills, ...selectedFrameworkSkills, ...(selectedArchitectureSkill ? [selectedArchitectureSkill] : []), ...selectedWorkflowSkills]
|
|
33
33
|
.map((skill) => `- ${skill.routingInstruction}`)
|
|
34
34
|
.join('\n');
|
|
35
35
|
return contents.replace('{{OPTIONAL_SKILL_ROUTING}}', optionalRouting);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
import { SIBU_VERSION, MANDATORY_SKILLS, SELECTABLE_ARCHITECTURE_SKILLS, SELECTABLE_FRAMEWORK_SKILLS, SELECTABLE_LANGUAGE_SKILLS, SUPPORTED_AGENTS } from './catalog.js';
|
|
3
|
+
import { SIBU_VERSION, MANDATORY_SKILLS, SELECTABLE_ARCHITECTURE_SKILLS, SELECTABLE_FRAMEWORK_SKILLS, SELECTABLE_LANGUAGE_SKILLS, SELECTABLE_WORKFLOW_SKILLS, SUPPORTED_AGENTS, } from './catalog.js';
|
|
4
4
|
import { sha256 } from './hash.js';
|
|
5
5
|
import { removeUndefinedFields } from './object.js';
|
|
6
6
|
import { readExistingState } from './state.js';
|
|
@@ -14,13 +14,17 @@ export function getSelectedFrameworkSkillsFromState(state) {
|
|
|
14
14
|
export function getSelectedArchitectureSkillFromState(state) {
|
|
15
15
|
return SELECTABLE_ARCHITECTURE_SKILLS.find((skill) => skill.id === state.selectedArchitectureSkill);
|
|
16
16
|
}
|
|
17
|
-
export function
|
|
17
|
+
export function getSelectedWorkflowSkillsFromState(state) {
|
|
18
|
+
return SELECTABLE_WORKFLOW_SKILLS.filter((skill) => state.selectedWorkflowSkills?.includes(skill.id));
|
|
19
|
+
}
|
|
20
|
+
export function getSelectedSkillTargetsForAgents(selectedAgents, selectedLanguageSkills, selectedFrameworkSkills, selectedArchitectureSkill, selectedWorkflowSkills = []) {
|
|
18
21
|
const skillTargets = new Map();
|
|
19
22
|
const selectedSkills = [
|
|
20
23
|
...MANDATORY_SKILLS,
|
|
21
24
|
...selectedLanguageSkills,
|
|
22
25
|
...selectedFrameworkSkills,
|
|
23
26
|
...(selectedArchitectureSkill ? [selectedArchitectureSkill] : []),
|
|
27
|
+
...selectedWorkflowSkills,
|
|
24
28
|
];
|
|
25
29
|
for (const agent of selectedAgents) {
|
|
26
30
|
for (const skill of selectedSkills) {
|
|
@@ -36,7 +40,7 @@ export function getSelectedSkillTargetsForAgents(selectedAgents, selectedLanguag
|
|
|
36
40
|
}
|
|
37
41
|
return [...skillTargets.values()];
|
|
38
42
|
}
|
|
39
|
-
export function getWorkflowTargets(rootPath, selectedAgents, selectedLanguageSkills = [], selectedFrameworkSkills = [], selectedArchitectureSkill) {
|
|
43
|
+
export function getWorkflowTargets(rootPath, selectedAgents, selectedLanguageSkills = [], selectedFrameworkSkills = [], selectedArchitectureSkill, selectedWorkflowSkills = []) {
|
|
40
44
|
return [
|
|
41
45
|
{
|
|
42
46
|
label: 'AGENTS.md',
|
|
@@ -57,7 +61,7 @@ export function getWorkflowTargets(rootPath, selectedAgents, selectedLanguageSki
|
|
|
57
61
|
},
|
|
58
62
|
];
|
|
59
63
|
}),
|
|
60
|
-
...getSelectedSkillTargetsForAgents(selectedAgents, selectedLanguageSkills, selectedFrameworkSkills, selectedArchitectureSkill).map((skillTarget) => ({
|
|
64
|
+
...getSelectedSkillTargetsForAgents(selectedAgents, selectedLanguageSkills, selectedFrameworkSkills, selectedArchitectureSkill, selectedWorkflowSkills).map((skillTarget) => ({
|
|
61
65
|
label: skillTarget.targetRelativePath,
|
|
62
66
|
targetPath: path.join(rootPath, skillTarget.targetRelativePath),
|
|
63
67
|
templateRelativePath: skillTarget.templateRelativePath,
|
|
@@ -65,7 +69,7 @@ export function getWorkflowTargets(rootPath, selectedAgents, selectedLanguageSki
|
|
|
65
69
|
})),
|
|
66
70
|
];
|
|
67
71
|
}
|
|
68
|
-
export function renderMissingWorkflowFiles({ missingTargets, overview, selectedLanguageSkills, selectedFrameworkSkills, selectedArchitectureSkill, }) {
|
|
72
|
+
export function renderMissingWorkflowFiles({ missingTargets, overview, selectedLanguageSkills, selectedFrameworkSkills, selectedArchitectureSkill, selectedWorkflowSkills = [], }) {
|
|
69
73
|
return missingTargets.map((target) => {
|
|
70
74
|
let contents = readTemplate(target.templateRelativePath);
|
|
71
75
|
if (target.requiresProjectOverview) {
|
|
@@ -74,7 +78,7 @@ export function renderMissingWorkflowFiles({ missingTargets, overview, selectedL
|
|
|
74
78
|
}
|
|
75
79
|
contents = contents.replace('{{PROJECT_OVERVIEW}}', overview.trim());
|
|
76
80
|
}
|
|
77
|
-
contents = renderSkillRouting(contents, selectedLanguageSkills, selectedFrameworkSkills, selectedArchitectureSkill);
|
|
81
|
+
contents = renderSkillRouting(contents, selectedLanguageSkills, selectedFrameworkSkills, selectedArchitectureSkill, selectedWorkflowSkills);
|
|
78
82
|
return {
|
|
79
83
|
label: target.label,
|
|
80
84
|
targetPath: target.targetPath,
|
|
@@ -82,7 +86,7 @@ export function renderMissingWorkflowFiles({ missingTargets, overview, selectedL
|
|
|
82
86
|
};
|
|
83
87
|
});
|
|
84
88
|
}
|
|
85
|
-
export function writeSibuState({ rootPath, statePath, selectedAgents, selectedLanguageSkills, selectedFrameworkSkills, selectedArchitectureSkill, targets, }) {
|
|
89
|
+
export function writeSibuState({ rootPath, statePath, selectedAgents, selectedLanguageSkills, selectedFrameworkSkills, selectedArchitectureSkill, selectedWorkflowSkills = [], targets, }) {
|
|
86
90
|
const previousState = readExistingState(statePath);
|
|
87
91
|
const now = new Date().toISOString();
|
|
88
92
|
const manifest = readTemplateManifest();
|
|
@@ -95,6 +99,7 @@ export function writeSibuState({ rootPath, statePath, selectedAgents, selectedLa
|
|
|
95
99
|
selectedLanguageSkills: selectedLanguageSkills.map((skill) => skill.id),
|
|
96
100
|
selectedFrameworkSkills: selectedFrameworkSkills.map((skill) => skill.id),
|
|
97
101
|
selectedArchitectureSkill: selectedArchitectureSkill?.id,
|
|
102
|
+
selectedWorkflowSkills: selectedWorkflowSkills.map((skill) => skill.id),
|
|
98
103
|
managedFiles: Object.fromEntries(targets
|
|
99
104
|
.filter((target) => fs.existsSync(target.targetPath))
|
|
100
105
|
.map((target) => {
|
package/package.json
CHANGED
package/templates/manifest.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"templateVersion": "
|
|
2
|
+
"templateVersion": "47",
|
|
3
3
|
"templates": {
|
|
4
4
|
"AGENTS.md": {
|
|
5
5
|
"version": "20",
|
|
@@ -54,10 +54,10 @@
|
|
|
54
54
|
]
|
|
55
55
|
},
|
|
56
56
|
"skills/technical-design-writer/SKILL.md": {
|
|
57
|
-
"version": "
|
|
57
|
+
"version": "9",
|
|
58
58
|
"description": "Mandatory technical design writer skill installed once at the shared .agents/skills workspace path.",
|
|
59
59
|
"changes": [
|
|
60
|
-
"
|
|
60
|
+
"Requires UI-related technical designs to read ux.md and treat UX mockups as binding implementation goals instead of redesign targets."
|
|
61
61
|
]
|
|
62
62
|
},
|
|
63
63
|
"skills/typescript/SKILL.md": {
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
"version": "1",
|
|
72
72
|
"description": "Selectable Go skill installed when Go language support is selected.",
|
|
73
73
|
"changes": [
|
|
74
|
-
"Adds an optional Go skill with concise, Effective Go
|
|
74
|
+
"Adds an optional Go skill with concise, Effective Go\u2013style guidance for .go files, package APIs, interfaces, errors, receivers, concurrency, and tests."
|
|
75
75
|
]
|
|
76
76
|
},
|
|
77
77
|
"skills/architecture/ddd-hexagonal/SKILL.md": {
|
|
@@ -103,28 +103,38 @@
|
|
|
103
103
|
]
|
|
104
104
|
},
|
|
105
105
|
"skills/scrum-master-planner/SKILL.md": {
|
|
106
|
-
"version": "
|
|
106
|
+
"version": "3",
|
|
107
107
|
"description": "Mandatory Scrum planner skill for creating pragmatic Epics and User Stories from approved feature and technical design docs.",
|
|
108
108
|
"changes": [
|
|
109
|
-
"
|
|
110
|
-
"Adds two-digit execution-order filename prefixes for User Stories, with shared numbers indicating parallelizable work."
|
|
109
|
+
"Requires UI-related Scrum planning to read ux.md and preserve binding mockups in Epics and User Stories."
|
|
111
110
|
]
|
|
112
111
|
},
|
|
113
112
|
"skills/ai-implementation-planner/SKILL.md": {
|
|
114
|
-
"version": "
|
|
113
|
+
"version": "5",
|
|
115
114
|
"description": "Mandatory AI implementation planner skill for turning one approved User Story into small, story-local implementation step files.",
|
|
116
115
|
"changes": [
|
|
117
|
-
"
|
|
118
|
-
"Updates the step-file format to use Markdown headings for Step, Goal, Scope, Files, and Done when sections."
|
|
116
|
+
"Requires UI-related implementation plans to read ux.md and turn binding mockups into implementation steps without redesigning them."
|
|
119
117
|
]
|
|
120
118
|
},
|
|
121
119
|
"skills/ai-implementation-plan-executor/SKILL.md": {
|
|
122
|
-
"version": "
|
|
120
|
+
"version": "6",
|
|
123
121
|
"description": "Mandatory AI implementation plan executor skill for implementing existing story implementation plans one reviewed step at a time.",
|
|
124
122
|
"changes": [
|
|
125
|
-
"
|
|
126
|
-
|
|
127
|
-
|
|
123
|
+
"Requires UI-related implementation execution to read ux.md and implement binding mockups without redesigning them."
|
|
124
|
+
]
|
|
125
|
+
},
|
|
126
|
+
"skills/ai-prompt-engineer-master/SKILL.md": {
|
|
127
|
+
"version": "1",
|
|
128
|
+
"description": "Selectable AI prompt engineering skill for prompt creation, optimization, compression, and evaluation.",
|
|
129
|
+
"changes": [
|
|
130
|
+
"Adds an optional AI prompt engineering skill for projects that create, improve, evaluate, or maintain reusable prompts for AI models, agents, tools, and coding assistants."
|
|
131
|
+
]
|
|
132
|
+
},
|
|
133
|
+
"skills/ux-expert/SKILL.md": {
|
|
134
|
+
"version": "1",
|
|
135
|
+
"description": "Selectable UX expert skill for UI-changing features, responsive design, flows, states, accessibility, and binding mockups.",
|
|
136
|
+
"changes": [
|
|
137
|
+
"Adds an optional UX expert skill for UI-changing features, including implementation-ready UX guidance and binding mockups."
|
|
128
138
|
]
|
|
129
139
|
}
|
|
130
140
|
}
|
|
@@ -33,10 +33,15 @@ docs/features/<feature-slug>/epics/<epic-slug>/stories/<order>-<story-slug>.impl
|
|
|
33
33
|
docs/features/<feature-slug>/epics/<epic-slug>/epic_brief.md
|
|
34
34
|
docs/features/<feature-slug>/feature_brief.md
|
|
35
35
|
docs/features/<feature-slug>/technical_design.md
|
|
36
|
+
docs/features/<feature-slug>/ux.md # when the story, step, or feature has UI impact
|
|
36
37
|
```
|
|
37
38
|
|
|
38
39
|
Also read `docs/product-vision.md` when product fit, target user, scope boundaries, or success signals are ambiguous.
|
|
39
40
|
|
|
41
|
+
If the story, current step, or feature has UI impact and `docs/features/<feature-slug>/ux.md` is missing, stop and ask the user to create the UX spec with `ux-expert` before implementation.
|
|
42
|
+
|
|
43
|
+
When `ux.md` includes mockups, treat them as binding UI goals. Implementation must preserve the mockup structure, hierarchy, visible content, dominant interactions, major visual emphasis, and breakpoint-specific layout. Do not redesign the UI during execution; implement the approved UX and stop if technical constraints require a UX revision.
|
|
44
|
+
|
|
40
45
|
Before changing code, read and apply the implementation skills required by the plan and repository routing:
|
|
41
46
|
|
|
42
47
|
- always read and apply `clean-code`
|
|
@@ -30,10 +30,15 @@ docs/features/<feature-slug>/epics/<epic-slug>/stories/<order>-<story-slug>.md
|
|
|
30
30
|
docs/features/<feature-slug>/epics/<epic-slug>/epic_brief.md
|
|
31
31
|
docs/features/<feature-slug>/feature_brief.md
|
|
32
32
|
docs/features/<feature-slug>/technical_design.md
|
|
33
|
+
docs/features/<feature-slug>/ux.md # when the story or feature has UI impact
|
|
33
34
|
```
|
|
34
35
|
|
|
35
36
|
Also read `docs/product-vision.md` when product fit, target user, scope boundaries, or success signals are ambiguous.
|
|
36
37
|
|
|
38
|
+
If the story or feature has UI impact and `docs/features/<feature-slug>/ux.md` is missing, stop and ask the user to create the UX spec with `ux-expert` before implementation planning.
|
|
39
|
+
|
|
40
|
+
When `ux.md` includes mockups, treat them as binding UI goals. Implementation steps must preserve the mockup structure, hierarchy, visible content, dominant interactions, major visual emphasis, and breakpoint-specific layout. Do not redesign the UI in the implementation plan; plan code steps that implement the approved UX and stop if technical constraints require a UX revision.
|
|
41
|
+
|
|
37
42
|
Before writing the step files, read and apply the required planning skills as source context:
|
|
38
43
|
|
|
39
44
|
- always read and apply `clean-code`
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ai-prompt-engineer-master
|
|
3
|
+
description: "Use when creating, rewriting, optimizing, compressing, evaluating, or systematizing prompts for AI models, agents, tools, coding assistants, product workflows, or reusable prompt templates. Focus on top-quality results with the smallest effective token budget: preserve or improve output quality first, then remove every token that does not contribute to that quality."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# AI Prompt Engineer Master
|
|
7
|
+
|
|
8
|
+
## Core principle
|
|
9
|
+
|
|
10
|
+
Optimize for the **smallest prompt that reliably produces the required quality**.
|
|
11
|
+
|
|
12
|
+
This skill is model-agnostic: adapt wording to the target model when known, but do not assume any specific provider or model family.
|
|
13
|
+
|
|
14
|
+
Do not trade quality away for fewer tokens. First define the quality bar, then find the leanest prompt that meets it.
|
|
15
|
+
|
|
16
|
+
## Workflow
|
|
17
|
+
|
|
18
|
+
1. **Clarify the prompt job**
|
|
19
|
+
- Identify the target model or agent if known.
|
|
20
|
+
- Identify the user, task, input context, output format, quality bar, and failure modes.
|
|
21
|
+
- Ask only when missing information would materially change the prompt.
|
|
22
|
+
|
|
23
|
+
2. **Define the quality contract**
|
|
24
|
+
- State the outcome the prompt must achieve.
|
|
25
|
+
- Include success criteria, required constraints, and non-negotiable safety or compliance rules.
|
|
26
|
+
- Define what the model should do when context is missing, ambiguous, or contradictory.
|
|
27
|
+
|
|
28
|
+
3. **Design outcome-first**
|
|
29
|
+
- Prefer destination over step-by-step process.
|
|
30
|
+
- Use process instructions only when order, auditability, or tool behavior truly matters.
|
|
31
|
+
- Put stable instructions before dynamic task/input content.
|
|
32
|
+
|
|
33
|
+
4. **Compress without quality loss**
|
|
34
|
+
- Remove duplicated rules, generic advice, filler, motivational language, and obvious model capabilities.
|
|
35
|
+
- Replace long explanations with precise constraints or decision rules.
|
|
36
|
+
- Merge overlapping instructions.
|
|
37
|
+
- Keep examples only when they prevent likely errors or define subtle style/format expectations.
|
|
38
|
+
|
|
39
|
+
5. **Make the output easy to verify**
|
|
40
|
+
- Specify the output shape only as tightly as needed.
|
|
41
|
+
- Prefer schemas, examples, or bullets when they reduce ambiguity.
|
|
42
|
+
- Include acceptance checks for high-stakes or reusable prompts.
|
|
43
|
+
|
|
44
|
+
6. **Deliver usable artifacts**
|
|
45
|
+
- Provide the final prompt in a copy-ready block.
|
|
46
|
+
- If helpful, include a short note explaining the token-saving choices.
|
|
47
|
+
- For reusable prompts, separate stable prompt text from runtime variables.
|
|
48
|
+
|
|
49
|
+
## Prompt quality checklist
|
|
50
|
+
|
|
51
|
+
A strong prompt usually has:
|
|
52
|
+
|
|
53
|
+
- **Role or perspective** only when it changes behavior.
|
|
54
|
+
- **Task** stated as a concrete outcome.
|
|
55
|
+
- **Context** limited to information the model needs.
|
|
56
|
+
- **Constraints** that prevent real failures.
|
|
57
|
+
- **Output format** specific enough for the consumer.
|
|
58
|
+
- **Missing-context behavior** so the model does not invent facts.
|
|
59
|
+
- **Tone/style** only when user-facing quality depends on it.
|
|
60
|
+
- **Validation criteria** for important workflows.
|
|
61
|
+
|
|
62
|
+
## Token discipline rules
|
|
63
|
+
|
|
64
|
+
Prefer:
|
|
65
|
+
|
|
66
|
+
- “Return JSON matching this schema” over a prose explanation of each field when a schema is available.
|
|
67
|
+
- “If evidence is missing, say what is missing” over long hallucination warnings.
|
|
68
|
+
- “Use concise bullets” over multiple style paragraphs.
|
|
69
|
+
- One representative example over many near-duplicates.
|
|
70
|
+
- A short decision rule over absolute words like “always” or “never” unless the rule is truly invariant.
|
|
71
|
+
|
|
72
|
+
Avoid:
|
|
73
|
+
|
|
74
|
+
- Repeating the same constraint in multiple sections.
|
|
75
|
+
- Explaining why the model should follow ordinary instructions.
|
|
76
|
+
- Adding chain-of-thought requests.
|
|
77
|
+
- Keeping legacy prompt scaffolding because it “might help.”
|
|
78
|
+
- Compressing away domain terms, examples, or constraints that carry real quality value.
|
|
79
|
+
|
|
80
|
+
## Output pattern
|
|
81
|
+
|
|
82
|
+
When optimizing a prompt, use this structure unless the user asks otherwise:
|
|
83
|
+
|
|
84
|
+
```md
|
|
85
|
+
## Final prompt
|
|
86
|
+
|
|
87
|
+
<prompt>
|
|
88
|
+
|
|
89
|
+
## Why this is token-efficient
|
|
90
|
+
|
|
91
|
+
- <1-3 bullets about what was preserved or removed>
|
|
92
|
+
|
|
93
|
+
## Optional stronger version
|
|
94
|
+
|
|
95
|
+
<only include if quality risks justify extra tokens>
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
If the user only wants the prompt, return only the final prompt.
|
|
@@ -18,10 +18,15 @@ Before planning, read:
|
|
|
18
18
|
```txt
|
|
19
19
|
docs/features/<feature-slug>/feature_brief.md
|
|
20
20
|
docs/features/<feature-slug>/technical_design.md
|
|
21
|
+
docs/features/<feature-slug>/ux.md # when the feature has UI impact
|
|
21
22
|
```
|
|
22
23
|
|
|
23
24
|
Also read `docs/product-vision.md` when it exists and the planning decision depends on product fit, scope boundaries, user value, or success signals.
|
|
24
25
|
|
|
26
|
+
If the feature has UI impact and `docs/features/<feature-slug>/ux.md` is missing, stop and ask the user to create the UX spec with `ux-expert` before Scrum planning.
|
|
27
|
+
|
|
28
|
+
When `ux.md` includes mockups, treat them as binding UI goals. Epics and Stories must preserve the mockup structure, hierarchy, visible content, dominant interactions, major visual emphasis, and breakpoint-specific layout. Do not redesign the UI in Scrum planning; create delivery slices that implement the approved UX.
|
|
29
|
+
|
|
25
30
|
## Hard start rule
|
|
26
31
|
|
|
27
32
|
Do not create Epics or User Stories if either the feature brief or technical design is missing.
|
|
@@ -15,9 +15,10 @@ Before writing, read:
|
|
|
15
15
|
|
|
16
16
|
1. `docs/product-vision.md`
|
|
17
17
|
2. the feature brief
|
|
18
|
-
3. `
|
|
19
|
-
4.
|
|
20
|
-
5.
|
|
18
|
+
3. `docs/features/<feature-slug>/ux.md` when the feature has UI impact
|
|
19
|
+
4. `clean-code`
|
|
20
|
+
5. any selected architecture, language, or framework skills that apply
|
|
21
|
+
6. relevant existing repo files and flows
|
|
21
22
|
|
|
22
23
|
Apply those inputs. Do not summarize them back into the technical design unless a specific implication changes the implementation.
|
|
23
24
|
|
|
@@ -25,7 +26,11 @@ Apply those inputs. Do not summarize them back into the technical design unless
|
|
|
25
26
|
|
|
26
27
|
Require a Markdown feature brief. If the user only has a vague idea, route to `feature-brief-writer` first.
|
|
27
28
|
|
|
28
|
-
If the feature has UI impact,
|
|
29
|
+
If the feature has UI impact, require `docs/features/<feature-slug>/ux.md`. If it is missing, stop and ask the user to create the UX spec with `ux-expert` first.
|
|
30
|
+
|
|
31
|
+
## UX binding rule
|
|
32
|
+
|
|
33
|
+
For UI-related features, `ux.md` is source context, not inspiration. If `ux.md` includes mockups, treat those mockups as binding UI goals for structure, hierarchy, visible content, dominant interactions, major visual emphasis, and breakpoint-specific layout. Do not redesign the mockups in the technical design. Translate them into implementation direction and call out only technical feasibility issues, missing states, or conflicts that require UX revision.
|
|
29
34
|
|
|
30
35
|
## Design stance
|
|
31
36
|
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ux-expert
|
|
3
|
+
description: Use this skill for UX/UI design after product definition when a feature has UI changes. Requires an approved Markdown product artifact (feature brief) that defines goals, scope, and acceptance criteria; if none exists, route to feature-brief-writer (and product-vision-writer if missing). Use for senior UX/UI direction, phone-first responsive design, breakpoint-specific layouts/components, user flows, information architecture, wireframes, concrete mockups, interaction states, accessibility, visual direction, creative UI concepts, and implementation-ready UI guidance.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# ux-expert
|
|
7
|
+
|
|
8
|
+
Act as a senior UX/UI designer. Turn an approved product artifact into usable, expressive, phone-first, implementation-ready UI direction. Do not include code, file paths, architecture, or framework-specific guidance.
|
|
9
|
+
|
|
10
|
+
## Required grounding
|
|
11
|
+
|
|
12
|
+
Read `docs/product-vision.md` and apply only relevant implications: target user, principles, voice, boundaries, trust expectations, success signal. Do not restate the full vision.
|
|
13
|
+
|
|
14
|
+
Require a product artifact such as `docs/features/<feature-slug>/feature_brief.md` that defines goal, scope, and acceptance criteria. If the user has only an idea, route to `feature-brief-writer` first. If the artifact says there is no UI impact, say so and do not invent UI work.
|
|
15
|
+
|
|
16
|
+
## Mockup authority rule
|
|
17
|
+
|
|
18
|
+
For UI-changing features, the UX artifact must include concrete mockups for affected screens, states, and breakpoints. Mockups are the source of truth for structure, hierarchy, visible content, dominant interactions, and major visual emphasis. Downstream technical design, stories, implementation plans, and implementation must follow them unless this UX spec is explicitly revised.
|
|
19
|
+
|
|
20
|
+
If a materially affected state/breakpoint lacks a mockup, UX work is incomplete.
|
|
21
|
+
|
|
22
|
+
## Confirmation behavior
|
|
23
|
+
|
|
24
|
+
Creating/updating the Markdown UX artifact is not a code change. Write it without pre-change confirmation when the target is clear and requested. Ask only when context is missing, the target is ambiguous, overwrite/destruction is possible, or code changes are required.
|
|
25
|
+
|
|
26
|
+
## UX principles
|
|
27
|
+
|
|
28
|
+
Design for user experience first, component reuse second. Prefer clear task completion, strong hierarchy, obvious affordances/feedback/recovery, progressive disclosure, accessibility, resilient states, and distinctive but shippable UI. Avoid generic SaaS/page-builder layouts, decorative clarity loss, desktop-first thinking, product scope changes, and technical architecture decisions.
|
|
29
|
+
|
|
30
|
+
## Phone-first responsive rule
|
|
31
|
+
|
|
32
|
+
Design phone first, then re-evaluate tablet and desktop as separate UX problems. Choose different layouts/components across breakpoints when that improves hierarchy, interaction, density, touch/pointer behavior, or content priority. Share components only when they remain the best experience.
|
|
33
|
+
|
|
34
|
+
## Workflow
|
|
35
|
+
|
|
36
|
+
1. Read product vision and feature brief.
|
|
37
|
+
2. Identify affected UI surfaces and whether UI work is valid.
|
|
38
|
+
3. Design phone-first flow, information architecture, and layout.
|
|
39
|
+
4. Re-evaluate tablet and desktop independently.
|
|
40
|
+
5. Define interaction states, failure/recovery behavior, accessibility requirements, and creative direction.
|
|
41
|
+
6. Create concrete mockups for primary screens, affected breakpoints, and critical states.
|
|
42
|
+
7. Write implementation-ready UX guidance only: flows, hierarchy, states, accessibility, visual direction.
|
|
43
|
+
|
|
44
|
+
## Output location
|
|
45
|
+
|
|
46
|
+
Write to `docs/features/<feature-slug>/ux.md` using the feature artifact slug. Keep same-feature artifacts together; do not write UX specs in product, technical design, story, or implementation-plan files.
|
|
47
|
+
|
|
48
|
+
## Mockup requirements
|
|
49
|
+
|
|
50
|
+
Mockups may be low fidelity but must be concrete and unambiguous: layout regions, visible content, hierarchy/emphasis, key controls, major state differences, and breakpoint changes. Use annotated text/box wireframes when enough. Show decisions that downstream implementation must not improvise.
|
|
51
|
+
|
|
52
|
+
## Output format
|
|
53
|
+
|
|
54
|
+
Use only helpful sections from this shape:
|
|
55
|
+
|
|
56
|
+
```md
|
|
57
|
+
# UX Spec: <Feature Name>
|
|
58
|
+
|
|
59
|
+
## Input Product Artifact
|
|
60
|
+
## Product Vision Implications
|
|
61
|
+
## UX Intent
|
|
62
|
+
## Affected Surfaces
|
|
63
|
+
## Phone-First User Flow
|
|
64
|
+
## Information Architecture
|
|
65
|
+
## Phone Layout
|
|
66
|
+
## Tablet Layout
|
|
67
|
+
## Desktop Layout
|
|
68
|
+
## Binding Mockups
|
|
69
|
+
### Phone
|
|
70
|
+
```text
|
|
71
|
+
<Annotated phone mockup>
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Tablet
|
|
75
|
+
```text
|
|
76
|
+
<Annotated tablet mockup>
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Desktop
|
|
80
|
+
```text
|
|
81
|
+
<Annotated desktop mockup>
|
|
82
|
+
```
|
|
83
|
+
## Breakpoint-Specific Component Strategy
|
|
84
|
+
## Interaction States
|
|
85
|
+
## Accessibility Requirements
|
|
86
|
+
## Visual Direction
|
|
87
|
+
## Creative Opportunities
|
|
88
|
+
## Implementation Notes
|
|
89
|
+
## UI Authority Rule
|
|
90
|
+
## Open UX Questions
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
The Binding Mockups section is authoritative for downstream work unless this UX spec is revised.
|