@juancr11/sibu 0.1.0 → 0.3.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 +19 -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 +5 -3
- package/templates/AGENTS.md +3 -2
- package/templates/manifest.json +16 -7
- package/templates/skills/ai-implementation-plan-executor/SKILL.md +31 -4
- package/templates/skills/ai-prompt-engineer-master/SKILL.md +98 -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,21 @@ 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
|
+
];
|
|
157
172
|
export const SUPPORTED_AGENTS = [
|
|
158
173
|
{
|
|
159
174
|
id: 'codex',
|
|
@@ -195,5 +210,9 @@ export function resolveSelectableSkillById(skillId) {
|
|
|
195
210
|
if (architectureSkill) {
|
|
196
211
|
return { ok: true, resolved: { kind: 'architecture', skill: architectureSkill } };
|
|
197
212
|
}
|
|
213
|
+
const workflowSkill = SELECTABLE_WORKFLOW_SKILLS.find((skill) => skill.id === skillId);
|
|
214
|
+
if (workflowSkill) {
|
|
215
|
+
return { ok: true, resolved: { kind: 'workflow', skill: workflowSkill } };
|
|
216
|
+
}
|
|
198
217
|
return { ok: false, message: `Unknown skill \`${skillId}\`. Run \`sibu skills list\` to see available skills.` };
|
|
199
218
|
}
|
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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juancr11/sibu",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "CLI for setting up a local AI-augmented development workflow.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -27,15 +27,17 @@
|
|
|
27
27
|
"build": "tsc && chmod +x bin/sibu.js",
|
|
28
28
|
"check": "tsc --noEmit",
|
|
29
29
|
"verify": "pnpm build && pnpm check && pnpm test",
|
|
30
|
+
"admin:changelog": "node ./bin/admin/changelog.js",
|
|
30
31
|
"dev:link": "pnpm install && pnpm build && pnpm link --global",
|
|
31
32
|
"dev:unlink": "pnpm unlink --global sibu",
|
|
32
33
|
"prepack": "pnpm run build",
|
|
33
34
|
"smoke:init": "node ./bin/sibu.js init",
|
|
34
|
-
"test": "pnpm build && node --test bin/shared/catalog.test.js bin/shared/npm-version.test.js bin/shared/prompts.test.js bin/shared/workflow-targets.test.js bin/shared/workflow-mutation-readiness.test.js bin/features/doctor-project/handler.test.js bin/features/use-skill/handler.test.js bin/features/stop-managing-file/handler.test.js",
|
|
35
|
+
"test": "pnpm build && node --test bin/shared/catalog.test.js bin/shared/npm-version.test.js bin/shared/prompts.test.js bin/shared/workflow-targets.test.js bin/shared/workflow-mutation-readiness.test.js bin/admin/generate-changelog/handler.test.js bin/admin/release.test.js bin/admin/release-workflow/handler.test.js bin/admin/release-workflow/package-json.test.js bin/features/doctor-project/handler.test.js bin/features/use-skill/handler.test.js bin/features/stop-managing-file/handler.test.js",
|
|
35
36
|
"validate:packed-runtime": "node ./scripts/validate-packed-cli-runtime.mjs",
|
|
36
37
|
"validate:doctor-version-advisory": "pnpm build && node ./scripts/validate-doctor-version-advisory.mjs",
|
|
37
38
|
"validate:post-update-doctor-drift": "pnpm build && node ./scripts/validate-post-update-doctor-drift.mjs",
|
|
38
|
-
"validate:release": "pnpm verify && npm pack && pnpm run validate:packed-runtime && pnpm run validate:doctor-version-advisory && pnpm run validate:post-update-doctor-drift"
|
|
39
|
+
"validate:release": "pnpm verify && npm pack && pnpm run validate:packed-runtime && pnpm run validate:doctor-version-advisory && pnpm run validate:post-update-doctor-drift",
|
|
40
|
+
"admin:release": "node ./bin/admin/release.js"
|
|
39
41
|
},
|
|
40
42
|
"keywords": [
|
|
41
43
|
"ai",
|
package/templates/AGENTS.md
CHANGED
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
|
|
14
14
|
## Agent-specific instructions
|
|
15
15
|
|
|
16
|
-
- Before any task that
|
|
16
|
+
- Before any task that writes or modifies code, propose a brief plan and wait for user confirmation once per requested task.
|
|
17
|
+
- For read-only work, research, planning, documentation-only edits, or other non-code changes, do not ask for confirmation unless the action is destructive, risky, ambiguous, or explicitly requires user approval.
|
|
17
18
|
- After confirmation, proceed with all agreed in-scope changes without re-asking.
|
|
18
19
|
- Ask again only if the scope changes materially, the approach becomes materially more complex or risky, or the user explicitly asks to review before continuing.
|
|
19
20
|
- Use Conventional Commits 1.0.0 for commit messages.
|
|
@@ -33,7 +34,7 @@
|
|
|
33
34
|
- For requests to create, revise, or clarify a technical design, implementation-oriented design doc, architecture approach, technical tradeoffs, technical risks, or implementation plan for an approved feature, use `technical-design-writer`.
|
|
34
35
|
- For requests to create Epics, User Stories, Scrum planning artifacts, backlog slices, or delivery plans from an approved feature brief and technical design, use `scrum-master-planner`.
|
|
35
36
|
- For requests to turn a specific User Story into an implementation checklist, coding plan, step-by-step execution plan, or baby-step plan, use `ai-implementation-planner`.
|
|
36
|
-
- For requests to implement, execute, continue, or work through an existing story implementation plan under `docs/features/<feature-slug>/epics/<epic-slug>/stories/<order>-<story-slug>.impl_plan/`, use `ai-implementation-plan-executor
|
|
37
|
+
- For requests to implement, execute, continue, or work through a specific User Story under `docs/features/<feature-slug>/epics/<epic-slug>/stories/<order>-<story-slug>.md` or an existing story implementation plan under `docs/features/<feature-slug>/epics/<epic-slug>/stories/<order>-<story-slug>.impl_plan/`, use `ai-implementation-plan-executor`; the executor must stop and direct the user to `ai-implementation-planner` when the story plan is missing.
|
|
37
38
|
{{OPTIONAL_SKILL_ROUTING}}
|
|
38
39
|
|
|
39
40
|
## Sibu maintenance
|
package/templates/manifest.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
|
-
"templateVersion": "
|
|
2
|
+
"templateVersion": "46",
|
|
3
3
|
"templates": {
|
|
4
4
|
"AGENTS.md": {
|
|
5
|
-
"version": "
|
|
5
|
+
"version": "20",
|
|
6
6
|
"description": "Project-level agent instructions and Sibu maintenance guidance.",
|
|
7
7
|
"changes": [
|
|
8
|
-
"
|
|
8
|
+
"Routes User Story implementation requests to the AI implementation plan executor, even when the story plan may still be missing.",
|
|
9
|
+
"Clarifies that the executor should direct users to the AI implementation planner when a User Story has no implementation plan."
|
|
9
10
|
]
|
|
10
11
|
},
|
|
11
12
|
".codex/config.toml": {
|
|
@@ -70,7 +71,7 @@
|
|
|
70
71
|
"version": "1",
|
|
71
72
|
"description": "Selectable Go skill installed when Go language support is selected.",
|
|
72
73
|
"changes": [
|
|
73
|
-
"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."
|
|
74
75
|
]
|
|
75
76
|
},
|
|
76
77
|
"skills/architecture/ddd-hexagonal/SKILL.md": {
|
|
@@ -118,11 +119,19 @@
|
|
|
118
119
|
]
|
|
119
120
|
},
|
|
120
121
|
"skills/ai-implementation-plan-executor/SKILL.md": {
|
|
121
|
-
"version": "
|
|
122
|
+
"version": "5",
|
|
122
123
|
"description": "Mandatory AI implementation plan executor skill for implementing existing story implementation plans one reviewed step at a time.",
|
|
123
124
|
"changes": [
|
|
124
|
-
"
|
|
125
|
-
"
|
|
125
|
+
"Clarifies that missing story implementation plans must be created with the AI implementation planner before execution.",
|
|
126
|
+
"Allows agents to begin the first unapproved implementation step immediately when a valid plan exists, while preserving review approval between steps.",
|
|
127
|
+
"Clarifies that after user approval, agents should mark the step approved, commit it, and continue to the next step without another pre-implementation confirmation."
|
|
128
|
+
]
|
|
129
|
+
},
|
|
130
|
+
"skills/ai-prompt-engineer-master/SKILL.md": {
|
|
131
|
+
"version": "1",
|
|
132
|
+
"description": "Selectable AI prompt engineering skill for prompt creation, optimization, compression, and evaluation.",
|
|
133
|
+
"changes": [
|
|
134
|
+
"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."
|
|
126
135
|
]
|
|
127
136
|
}
|
|
128
137
|
}
|
|
@@ -48,11 +48,18 @@ Inspect existing code, tests, scripts, and docs only as needed for the current s
|
|
|
48
48
|
|
|
49
49
|
## Hard start rule
|
|
50
50
|
|
|
51
|
-
If the `.impl_plan/` folder does not exist, is empty, or has no ordered `.md` step files:
|
|
51
|
+
If the user provides a User Story file and the matching `.impl_plan/` folder does not exist, is empty, or has no ordered `.md` step files:
|
|
52
52
|
|
|
53
53
|
1. Stop.
|
|
54
54
|
2. Tell the user the implementation plan is missing.
|
|
55
|
-
3. Instruct the user to use `ai-implementation-planner` to create the implementation plan first.
|
|
55
|
+
3. Instruct the user to use `templates/skills/ai-implementation-planner/SKILL.md` to create the implementation plan first.
|
|
56
|
+
4. Do not infer steps from the story or technical design.
|
|
57
|
+
|
|
58
|
+
If the user provides an `.impl_plan/` folder and it does not exist, is empty, or has no ordered `.md` step files:
|
|
59
|
+
|
|
60
|
+
1. Stop.
|
|
61
|
+
2. Tell the user the implementation plan is missing or invalid.
|
|
62
|
+
3. Instruct the user to use `templates/skills/ai-implementation-planner/SKILL.md` to create or repair the implementation plan first.
|
|
56
63
|
4. Do not infer steps from the story or technical design.
|
|
57
64
|
|
|
58
65
|
If required source context is missing:
|
|
@@ -66,6 +73,8 @@ If required source context is missing:
|
|
|
66
73
|
|
|
67
74
|
Work on exactly one step at a time.
|
|
68
75
|
|
|
76
|
+
When a valid implementation plan exists, begin implementing the first unapproved step immediately. Do not ask for pre-implementation confirmation before changing code for that step. This is an explicit exception to repository-level instructions that normally require confirmation before code changes: selecting this executor skill and providing a valid plan is the user's confirmation to implement the current step.
|
|
77
|
+
|
|
69
78
|
A step file is considered approved only when it contains this section:
|
|
70
79
|
|
|
71
80
|
```md
|
|
@@ -78,7 +87,7 @@ When starting or resuming a plan:
|
|
|
78
87
|
|
|
79
88
|
1. Read all step files in filename order.
|
|
80
89
|
2. Identify the first step file that is not approved.
|
|
81
|
-
3. Implement only that step.
|
|
90
|
+
3. Implement only that step immediately, without asking for confirmation first.
|
|
82
91
|
4. Run the validation named in that step when practical.
|
|
83
92
|
5. Report what changed, validation results, and any risks.
|
|
84
93
|
6. Stop and wait for explicit user confirmation before moving to the next step.
|
|
@@ -103,10 +112,22 @@ When the user explicitly approves the current step, update that step file by add
|
|
|
103
112
|
|
|
104
113
|
Before writing the approval marker, identify the current Git user with `git config user.name`; if it is unavailable, use `git config user.email`. Use that value for `Approved by`. After writing the approval marker, commit all changes for the approved step before continuing. Use a Conventional Commits 1.0.0 message that describes the completed step. If the commit fails, stop and report the failure instead of continuing.
|
|
105
114
|
|
|
106
|
-
Then continue with the next unapproved step only after the approval marker is written and the approved step changes are committed.
|
|
115
|
+
Then continue with the next unapproved step immediately, without asking for another pre-implementation confirmation, only after the approval marker is written and the approved step changes are committed.
|
|
107
116
|
|
|
108
117
|
If the user asks to continue without clearly approving the current step, ask for explicit approval before marking it approved, committing, or moving on.
|
|
109
118
|
|
|
119
|
+
## Epic continuation check
|
|
120
|
+
|
|
121
|
+
When all step files in the current story implementation plan are approved and committed:
|
|
122
|
+
|
|
123
|
+
1. Inspect the current Epic's `stories/` folder in filename order.
|
|
124
|
+
2. Identify whether there is a next User Story after the completed story.
|
|
125
|
+
3. If a next User Story exists and its `.impl_plan/` folder exists with ordered step files, ask the user whether they want to implement that next story.
|
|
126
|
+
4. If a next User Story exists but its `.impl_plan/` folder is missing or empty, ask the user whether they want to plan that next story with `ai-implementation-planner`.
|
|
127
|
+
5. If there is no next User Story in the Epic, tell the user the Epic appears ready.
|
|
128
|
+
|
|
129
|
+
Do not automatically start planning or implementing the next story. This check is a handoff prompt after the current story is complete, not permission to continue without the user's explicit direction.
|
|
130
|
+
|
|
110
131
|
## Implementation rules
|
|
111
132
|
|
|
112
133
|
Do:
|
|
@@ -136,3 +157,9 @@ After implementing one step, briefly report:
|
|
|
136
157
|
- validation run and result
|
|
137
158
|
- any risks, blockers, or follow-up questions
|
|
138
159
|
- that you are waiting for user approval before marking the step approved, committing it, and continuing to the next step
|
|
160
|
+
|
|
161
|
+
After approving and committing the final step in a story implementation plan, also briefly report the Epic continuation check result:
|
|
162
|
+
|
|
163
|
+
- next story ready to implement
|
|
164
|
+
- next story needs an implementation plan
|
|
165
|
+
- or Epic appears ready
|
|
@@ -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.
|