@codename_inc/spectre 3.7.0 → 5.0.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/README.md +6 -7
- package/package.json +3 -2
- package/plugins/spectre/.claude-plugin/plugin.json +1 -1
- package/plugins/spectre/bin/spectre-register +5 -0
- package/plugins/spectre/hooks/hooks.json +3 -14
- package/plugins/spectre/hooks/scripts/bootstrap.mjs +98 -0
- package/plugins/spectre/hooks/scripts/handoff-resume.mjs +404 -0
- package/plugins/spectre/hooks/scripts/lib.mjs +82 -0
- package/plugins/spectre/hooks/scripts/load-knowledge.mjs +189 -0
- package/plugins/spectre/hooks/scripts/register_learning.mjs +264 -0
- package/plugins/spectre/hooks/scripts/{test_bootstrap.cjs → test_bootstrap.mjs} +12 -7
- package/plugins/spectre/hooks/scripts/{test_handoff-resume.cjs → test_handoff-resume.mjs} +13 -11
- package/plugins/spectre/hooks/scripts/{test_load-knowledge.cjs → test_load-knowledge.mjs} +103 -22
- package/plugins/spectre/hooks/scripts/test_register-learning.mjs +335 -0
- package/plugins/spectre/skills/apply/SKILL.md +87 -0
- package/plugins/spectre/{commands/architecture_review.md → skills/architecture_review/SKILL.md} +9 -0
- package/plugins/spectre/{commands/clean.md → skills/clean/SKILL.md} +9 -0
- package/plugins/spectre/{commands/code_review.md → skills/code_review/SKILL.md} +9 -0
- package/plugins/spectre/{commands/create_plan.md → skills/create_plan/SKILL.md} +9 -0
- package/plugins/spectre/{commands/create_tasks.md → skills/create_tasks/SKILL.md} +9 -0
- package/plugins/spectre/{commands/create_test_guide.md → skills/create_test_guide/SKILL.md} +9 -0
- package/plugins/spectre/{commands/evaluate.md → skills/evaluate/SKILL.md} +11 -2
- package/plugins/spectre/{commands/execute.md → skills/execute/SKILL.md} +12 -3
- package/plugins/spectre/{commands/fix.md → skills/fix/SKILL.md} +9 -0
- package/plugins/spectre/{commands/forget.md → skills/forget/SKILL.md} +9 -0
- package/plugins/spectre/skills/{spectre-guide → guide}/SKILL.md +6 -5
- package/plugins/spectre/{commands/handoff.md → skills/handoff/SKILL.md} +9 -0
- package/plugins/spectre/{commands/kickoff.md → skills/kickoff/SKILL.md} +9 -0
- package/plugins/spectre/skills/{spectre-learn → learn}/SKILL.md +19 -59
- package/plugins/spectre/skills/learn/references/recall-template.md +34 -0
- package/plugins/spectre/{commands/plan.md → skills/plan/SKILL.md} +66 -25
- package/plugins/spectre/{commands/plan_review.md → skills/plan_review/SKILL.md} +9 -0
- package/plugins/spectre/skills/prototype/SKILL.md +314 -0
- package/plugins/spectre/{commands/quick_dev.md → skills/quick_dev/SKILL.md} +9 -0
- package/plugins/spectre/{commands/rebase.md → skills/rebase/SKILL.md} +9 -0
- package/plugins/spectre/skills/recall/SKILL.md +17 -0
- package/plugins/spectre/{commands/research.md → skills/research/SKILL.md} +9 -0
- package/plugins/spectre/skills/scope/SKILL.md +174 -0
- package/plugins/spectre/{commands/ship.md → skills/ship/SKILL.md} +9 -0
- package/plugins/spectre/{commands/sweep.md → skills/sweep/SKILL.md} +9 -0
- package/plugins/spectre/skills/tdd/SKILL.md +111 -0
- package/plugins/spectre/{commands/test.md → skills/test/SKILL.md} +9 -0
- package/plugins/spectre/skills/ux/SKILL.md +121 -0
- package/plugins/spectre/{commands/validate.md → skills/validate/SKILL.md} +9 -0
- package/plugins/spectre-codex/agents/analyst.toml +117 -0
- package/plugins/spectre-codex/agents/dev.toml +65 -0
- package/plugins/spectre-codex/agents/finder.toml +101 -0
- package/plugins/spectre-codex/agents/patterns.toml +203 -0
- package/plugins/spectre-codex/agents/reviewer.toml +123 -0
- package/plugins/spectre-codex/agents/sync.toml +146 -0
- package/plugins/spectre-codex/agents/tester.toml +205 -0
- package/plugins/spectre-codex/agents/web-research.toml +104 -0
- package/plugins/spectre-codex/hooks/hooks.json +23 -0
- package/plugins/{spectre/hooks/scripts/bootstrap.cjs → spectre-codex/hooks/scripts/bootstrap.mjs} +15 -16
- package/plugins/{spectre/hooks/scripts/handoff-resume.cjs → spectre-codex/hooks/scripts/handoff-resume.mjs} +21 -27
- package/plugins/{spectre/hooks/scripts/lib.cjs → spectre-codex/hooks/scripts/lib.mjs} +3 -4
- package/plugins/spectre-codex/hooks/scripts/load-knowledge.mjs +189 -0
- package/plugins/spectre-codex/hooks/scripts/register_learning.mjs +264 -0
- package/plugins/spectre-codex/skills/apply/SKILL.md +87 -0
- package/plugins/spectre-codex/skills/architecture_review/SKILL.md +129 -0
- package/plugins/spectre-codex/skills/clean/SKILL.md +322 -0
- package/plugins/spectre-codex/skills/code_review/SKILL.md +417 -0
- package/plugins/spectre-codex/skills/create_plan/SKILL.md +126 -0
- package/plugins/spectre-codex/skills/create_tasks/SKILL.md +383 -0
- package/plugins/spectre-codex/skills/create_test_guide/SKILL.md +129 -0
- package/plugins/spectre-codex/skills/evaluate/SKILL.md +59 -0
- package/plugins/spectre-codex/skills/execute/SKILL.md +96 -0
- package/plugins/spectre-codex/skills/fix/SKILL.md +70 -0
- package/plugins/spectre-codex/skills/forget/SKILL.md +67 -0
- package/plugins/spectre-codex/skills/guide/SKILL.md +359 -0
- package/plugins/spectre-codex/skills/handoff/SKILL.md +170 -0
- package/plugins/spectre-codex/skills/kickoff/SKILL.md +124 -0
- package/plugins/spectre-codex/skills/learn/SKILL.md +595 -0
- package/plugins/{spectre/skills/spectre-learn → spectre-codex/skills/learn}/references/recall-template.md +4 -1
- package/plugins/spectre-codex/skills/plan/SKILL.md +211 -0
- package/plugins/spectre-codex/skills/plan_review/SKILL.md +42 -0
- package/plugins/spectre-codex/skills/prototype/SKILL.md +314 -0
- package/plugins/spectre-codex/skills/quick_dev/SKILL.md +110 -0
- package/plugins/spectre-codex/skills/rebase/SKILL.md +82 -0
- package/plugins/spectre-codex/skills/recall/SKILL.md +17 -0
- package/plugins/spectre-codex/skills/research/SKILL.md +168 -0
- package/plugins/spectre-codex/skills/scope/SKILL.md +174 -0
- package/plugins/spectre-codex/skills/ship/SKILL.md +181 -0
- package/plugins/spectre-codex/skills/sweep/SKILL.md +91 -0
- package/plugins/{spectre/skills/spectre-tdd → spectre-codex/skills/tdd}/SKILL.md +1 -1
- package/plugins/spectre-codex/skills/test/SKILL.md +389 -0
- package/plugins/spectre-codex/skills/ux/SKILL.md +121 -0
- package/plugins/spectre-codex/skills/validate/SKILL.md +352 -0
- package/src/config.test.js +6 -5
- package/src/install.test.js +100 -11
- package/src/lib/config.js +107 -54
- package/src/lib/constants.js +17 -23
- package/src/lib/doctor.js +19 -22
- package/src/lib/install.js +98 -313
- package/src/lib/knowledge.js +7 -37
- package/src/lib/paths.js +0 -12
- package/src/pack.test.js +87 -0
- package/plugins/spectre/commands/learn.md +0 -15
- package/plugins/spectre/commands/recall.md +0 -5
- package/plugins/spectre/commands/scope.md +0 -119
- package/plugins/spectre/commands/ux_spec.md +0 -91
- package/plugins/spectre/hooks/scripts/load-knowledge.cjs +0 -120
- package/plugins/spectre/hooks/scripts/precompact-warning.cjs +0 -19
- package/plugins/spectre/hooks/scripts/register_learning.cjs +0 -144
- package/plugins/spectre/hooks/scripts/test_register-learning.cjs +0 -146
- package/plugins/spectre/skills/spectre-apply/SKILL.md +0 -189
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* register_learning.mjs
|
|
5
|
+
*
|
|
6
|
+
* Registers a spectre learning and manages the project-level recall skill.
|
|
7
|
+
*
|
|
8
|
+
* Responsibilities:
|
|
9
|
+
* 1. Create/update registry at .claude/skills/spectre-recall/references/registry.toon
|
|
10
|
+
* 2. Read recall-template.md from plugin
|
|
11
|
+
* 3. Generate .claude/skills/spectre-recall/SKILL.md with embedded registry
|
|
12
|
+
*
|
|
13
|
+
* Usage:
|
|
14
|
+
* node register_learning.mjs \
|
|
15
|
+
* --project-root "/path/to/project" \
|
|
16
|
+
* --skill-name "feature-my-feature" \
|
|
17
|
+
* --category "feature" \
|
|
18
|
+
* --triggers "keyword1, keyword2" \
|
|
19
|
+
* --description "Use when doing X or Y"
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import fs from 'node:fs';
|
|
23
|
+
import path from 'node:path';
|
|
24
|
+
import { fileURLToPath } from 'node:url';
|
|
25
|
+
|
|
26
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
27
|
+
const __dirname = path.dirname(__filename);
|
|
28
|
+
|
|
29
|
+
function getRegistryHeader() {
|
|
30
|
+
return [
|
|
31
|
+
'# SPECTRE Knowledge Registry',
|
|
32
|
+
'# Format: skill-name|category|triggers|description',
|
|
33
|
+
''
|
|
34
|
+
];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function updateRegistry(registryPath, entry, skillName) {
|
|
38
|
+
const entryPrefix = skillName + '|';
|
|
39
|
+
let lines;
|
|
40
|
+
|
|
41
|
+
if (fs.existsSync(registryPath)) {
|
|
42
|
+
const content = fs.readFileSync(registryPath, 'utf8').trim();
|
|
43
|
+
lines = content ? content.split('\n') : [];
|
|
44
|
+
} else {
|
|
45
|
+
lines = getRegistryHeader();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
let entryExists = false;
|
|
49
|
+
const updatedLines = [];
|
|
50
|
+
|
|
51
|
+
for (const line of lines) {
|
|
52
|
+
if (line.startsWith(entryPrefix)) {
|
|
53
|
+
updatedLines.push(entry);
|
|
54
|
+
entryExists = true;
|
|
55
|
+
} else {
|
|
56
|
+
updatedLines.push(line);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (!entryExists) {
|
|
61
|
+
updatedLines.push(entry);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
let content = updatedLines.join('\n');
|
|
65
|
+
if (!content.endsWith('\n')) {
|
|
66
|
+
content += '\n';
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
fs.writeFileSync(registryPath, content);
|
|
70
|
+
return content;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function generateFindSkill(findSkillPath, templatePath, registryContent) {
|
|
74
|
+
if (!fs.existsSync(templatePath)) {
|
|
75
|
+
process.stderr.write(`Warning: Template not found at ${templatePath}\n`);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const template = fs.readFileSync(templatePath, 'utf8');
|
|
80
|
+
const skillContent = template.replace('{{REGISTRY}}', registryContent.trim());
|
|
81
|
+
|
|
82
|
+
fs.mkdirSync(path.dirname(findSkillPath), { recursive: true });
|
|
83
|
+
fs.writeFileSync(findSkillPath, skillContent);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function parseFrontmatter(content) {
|
|
87
|
+
if (!content.startsWith('---')) return null;
|
|
88
|
+
const end = content.indexOf('\n---', 3);
|
|
89
|
+
if (end === -1) return null;
|
|
90
|
+
return {
|
|
91
|
+
fmBlock: content.slice(4, end),
|
|
92
|
+
body: content.slice(end + 4)
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function injectTriggerIntoSkill(skillPath, triggers) {
|
|
97
|
+
if (!fs.existsSync(skillPath)) return;
|
|
98
|
+
|
|
99
|
+
const content = fs.readFileSync(skillPath, 'utf8');
|
|
100
|
+
const parsed = parseFrontmatter(content);
|
|
101
|
+
if (!parsed) return;
|
|
102
|
+
|
|
103
|
+
const { fmBlock, body } = parsed;
|
|
104
|
+
|
|
105
|
+
const lines = fmBlock.split('\n');
|
|
106
|
+
const descIdx = lines.findIndex(l => /^description:\s*/.test(l));
|
|
107
|
+
if (descIdx === -1) return;
|
|
108
|
+
|
|
109
|
+
const descLine = lines[descIdx];
|
|
110
|
+
const rawValue = descLine.replace(/^description:\s*/, '').trim();
|
|
111
|
+
|
|
112
|
+
// Extract the plain description text and count lines to replace
|
|
113
|
+
let descText;
|
|
114
|
+
let linesToRemove = 1;
|
|
115
|
+
|
|
116
|
+
if (rawValue === '|' || rawValue === '>') {
|
|
117
|
+
// Block scalar — collect indented continuation lines
|
|
118
|
+
const continuationParts = [];
|
|
119
|
+
for (let i = descIdx + 1; i < lines.length; i++) {
|
|
120
|
+
if (/^\s+/.test(lines[i])) {
|
|
121
|
+
continuationParts.push(lines[i].trim());
|
|
122
|
+
linesToRemove++;
|
|
123
|
+
} else {
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
descText = continuationParts.join(' ');
|
|
128
|
+
} else {
|
|
129
|
+
descText = rawValue;
|
|
130
|
+
// Strip surrounding quotes
|
|
131
|
+
if ((descText.startsWith('"') && descText.endsWith('"')) ||
|
|
132
|
+
(descText.startsWith("'") && descText.endsWith("'"))) {
|
|
133
|
+
descText = descText.slice(1, -1);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Strip any existing TRIGGER clause so we can re-append with fresh triggers
|
|
138
|
+
descText = descText.replace(/\s*TRIGGER when:.*$/, '').trim();
|
|
139
|
+
|
|
140
|
+
// Single-line description with trigger appended
|
|
141
|
+
const newDesc = `description: ${descText} TRIGGER when: ${triggers}`;
|
|
142
|
+
|
|
143
|
+
// Idempotent: if the line is already exactly right, skip the write
|
|
144
|
+
if (linesToRemove === 1 && lines[descIdx] === newDesc) return;
|
|
145
|
+
|
|
146
|
+
lines.splice(descIdx, linesToRemove, newDesc);
|
|
147
|
+
|
|
148
|
+
const newFmBlock = lines.join('\n');
|
|
149
|
+
fs.writeFileSync(skillPath, `---\n${newFmBlock}\n---${body}`);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function migrateAllTriggers(projectRoot, registryContent) {
|
|
153
|
+
const skillsDir = skillBaseDir(projectRoot);
|
|
154
|
+
const lines = registryContent.trim().split('\n');
|
|
155
|
+
for (const line of lines) {
|
|
156
|
+
if (!line.trim() || line.startsWith('#')) continue;
|
|
157
|
+
const parts = line.split('|');
|
|
158
|
+
if (parts.length < 3) continue;
|
|
159
|
+
const skillName = parts[0];
|
|
160
|
+
const triggers = parts[2];
|
|
161
|
+
const skillPath = path.join(skillsDir, skillName, 'SKILL.md');
|
|
162
|
+
injectTriggerIntoSkill(skillPath, triggers);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function skillBaseDir(projectRoot) {
|
|
167
|
+
const agentsDir = path.join(projectRoot, '.agents', 'skills');
|
|
168
|
+
if (fs.existsSync(agentsDir)) return agentsDir;
|
|
169
|
+
return path.join(projectRoot, '.claude', 'skills');
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function resolvePluginSkillPath(pluginRoot, skillName, ...parts) {
|
|
173
|
+
const candidates = [
|
|
174
|
+
path.join(pluginRoot, 'skills', skillName, ...parts),
|
|
175
|
+
path.join(pluginRoot, '..', 'skills', skillName, ...parts),
|
|
176
|
+
];
|
|
177
|
+
|
|
178
|
+
for (const candidate of candidates) {
|
|
179
|
+
if (fs.existsSync(candidate)) {
|
|
180
|
+
return candidate;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return candidates[0];
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function parseArgs(argv) {
|
|
188
|
+
const args = {};
|
|
189
|
+
const flags = ['--project-root', '--skill-name', '--category', '--triggers', '--description'];
|
|
190
|
+
|
|
191
|
+
for (let i = 0; i < argv.length; i++) {
|
|
192
|
+
if (flags.includes(argv[i]) && i + 1 < argv.length) {
|
|
193
|
+
// Convert --project-root to projectRoot
|
|
194
|
+
const key = argv[i].slice(2).replace(/-([a-z])/g, (_, c) => c.toUpperCase());
|
|
195
|
+
args[key] = argv[i + 1];
|
|
196
|
+
i++;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
return args;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function main() {
|
|
204
|
+
const args = parseArgs(process.argv.slice(2));
|
|
205
|
+
|
|
206
|
+
const required = ['projectRoot', 'skillName', 'category', 'triggers', 'description'];
|
|
207
|
+
for (const key of required) {
|
|
208
|
+
if (!args[key]) {
|
|
209
|
+
process.stderr.write(`Error: missing required argument --${key.replace(/[A-Z]/g, c => '-' + c.toLowerCase())}\n`);
|
|
210
|
+
process.exit(1);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const projectRoot = args.projectRoot;
|
|
215
|
+
|
|
216
|
+
// New paths: registry lives inside spectre-recall skill
|
|
217
|
+
const recallDir = path.join(skillBaseDir(projectRoot), 'spectre-recall');
|
|
218
|
+
const registryDir = path.join(recallDir, 'references');
|
|
219
|
+
const registryPath = path.join(registryDir, 'registry.toon');
|
|
220
|
+
const recallSkillPath = path.join(recallDir, 'SKILL.md');
|
|
221
|
+
|
|
222
|
+
// Template is in the plugin — resolve via env var (hooks) or this script (manual invocation)
|
|
223
|
+
let pluginRoot;
|
|
224
|
+
if (process.env.CLAUDE_PLUGIN_ROOT) {
|
|
225
|
+
pluginRoot = process.env.CLAUDE_PLUGIN_ROOT;
|
|
226
|
+
} else {
|
|
227
|
+
// Fallback: resolve relative to this script
|
|
228
|
+
// Script is at: <plugin_root>/hooks/scripts/register_learning.mjs
|
|
229
|
+
pluginRoot = path.resolve(__dirname, '..', '..');
|
|
230
|
+
}
|
|
231
|
+
const templatePath = resolvePluginSkillPath(pluginRoot, 'learn', 'references', 'recall-template.md');
|
|
232
|
+
|
|
233
|
+
// Ensure directories exist
|
|
234
|
+
fs.mkdirSync(registryDir, { recursive: true });
|
|
235
|
+
|
|
236
|
+
// Build the registry entry
|
|
237
|
+
const entry = `${args.skillName}|${args.category}|${args.triggers}|${args.description}`;
|
|
238
|
+
|
|
239
|
+
// Update registry and get full content
|
|
240
|
+
const registryContent = updateRegistry(registryPath, entry, args.skillName);
|
|
241
|
+
|
|
242
|
+
// Generate recall skill with embedded registry
|
|
243
|
+
generateFindSkill(recallSkillPath, templatePath, registryContent);
|
|
244
|
+
|
|
245
|
+
// Reconcile triggers into all skill frontmatter descriptions
|
|
246
|
+
migrateAllTriggers(projectRoot, registryContent);
|
|
247
|
+
|
|
248
|
+
process.stdout.write(`Registered: ${entry}\n`);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
export {
|
|
252
|
+
getRegistryHeader,
|
|
253
|
+
updateRegistry,
|
|
254
|
+
generateFindSkill,
|
|
255
|
+
parseFrontmatter,
|
|
256
|
+
injectTriggerIntoSkill,
|
|
257
|
+
migrateAllTriggers,
|
|
258
|
+
resolvePluginSkillPath,
|
|
259
|
+
parseArgs
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
if (process.argv[1] && fs.realpathSync(path.resolve(process.argv[1])) === fs.realpathSync(__filename)) {
|
|
263
|
+
main();
|
|
264
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "apply"
|
|
3
|
+
description: "Use when starting implementation, debugging, or feature work on a project with captured knowledge."
|
|
4
|
+
user-invocable: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Apply Knowledge
|
|
8
|
+
|
|
9
|
+
## Why This Exists
|
|
10
|
+
|
|
11
|
+
SPECTRE captures knowledge — patterns, gotchas, decisions, and feature context — across sessions. Loading it first prevents repeated mistakes, maintains consistency, and tells you WHERE to look before searching.
|
|
12
|
+
|
|
13
|
+
## The Rule
|
|
14
|
+
|
|
15
|
+
<CRITICAL>
|
|
16
|
+
If ANY skill's triggers or description match your current task, you MUST load the skill FIRST using the Skill tool.
|
|
17
|
+
|
|
18
|
+
**Trigger matches are sufficient.** If a trigger word appears in the user's request, load the skill — you don't need the description to also match. Don't reframe the user's request to avoid triggers.
|
|
19
|
+
|
|
20
|
+
DO NOT search the codebase or dispatch agents BEFORE loading relevant knowledge — even if you think you already have enough context. Partial context from Read results or error messages is not a substitute for the complete picture in the skill.
|
|
21
|
+
|
|
22
|
+
**When a command explicitly tells you to load a skill, you MUST call the Skill tool to load it.** Do not improvise the workflow based on what you think the skill does. The skill defines a specific workflow with precise steps, output formats, file locations, and integrations. Your improvised version will be wrong.
|
|
23
|
+
|
|
24
|
+
**You are also responsible for keeping knowledge current.** After completing significant work, proactively check whether loaded skills need updating and whether new skills should be captured via `Skill(learn)`. Do NOT wait for the user to ask.
|
|
25
|
+
</CRITICAL>
|
|
26
|
+
|
|
27
|
+
## Path Convention
|
|
28
|
+
|
|
29
|
+
`{{project_root}}` refers to **the current working directory** (`$PWD`). NEVER traverse up to a parent git root or main worktree. If in a git worktree, `{{project_root}}` is the worktree — not the main repository.
|
|
30
|
+
|
|
31
|
+
## How to Find Skills
|
|
32
|
+
|
|
33
|
+
Your available skills are listed in context at the start of every session. Each skill's description includes `TRIGGER when:` keywords.
|
|
34
|
+
|
|
35
|
+
Scan the skill list for trigger matches against your current task. Load matches with `Skill({skill-name})`.
|
|
36
|
+
|
|
37
|
+
The registry at `{{project_root}}/.agents/skills/spectre-recall/references/registry.toon` remains the source of truth for registration, but you do NOT need to read it for discovery — the skill list already has what you need.
|
|
38
|
+
|
|
39
|
+
## Workflow
|
|
40
|
+
|
|
41
|
+
1. **Scan available skills** in your context — match trigger keywords or descriptions to your task
|
|
42
|
+
2. **For each match**, load the skill: `Skill({skill-name})`
|
|
43
|
+
3. **Apply the knowledge** — use it to guide your approach, know where to look
|
|
44
|
+
4. **Then proceed** — now you can search/implement with context
|
|
45
|
+
5. **No matches?** Proceed normally
|
|
46
|
+
|
|
47
|
+
## Keeping Knowledge Current
|
|
48
|
+
|
|
49
|
+
After completing work, check:
|
|
50
|
+
|
|
51
|
+
1. **Loaded skill now outdated?** → Update it immediately
|
|
52
|
+
2. **Discovered something capture-worthy?** (gotcha, pattern, decision) → Capture via `Skill(learn)`
|
|
53
|
+
3. **Changed key files, flows, or architecture?** → Update the relevant feature skill
|
|
54
|
+
4. **Made a decision with non-obvious rationale?** → Capture before the session ends
|
|
55
|
+
|
|
56
|
+
Stale knowledge is worse than no knowledge — it actively misleads future sessions. Update skills before moving to the next task.
|
|
57
|
+
|
|
58
|
+
## Red Flags
|
|
59
|
+
|
|
60
|
+
| Thought | Reality |
|
|
61
|
+
|---------|---------|
|
|
62
|
+
| "Let me search the codebase first" | Knowledge tells you WHERE to search. Load the skill first. |
|
|
63
|
+
| "I already have context from a Read/system message" | Partial context is dangerous. The skill has the full picture — including related changes you don't know about yet. |
|
|
64
|
+
| "This seems simple / the edit is surgical" | Simple tasks benefit from captured patterns. Skills reveal if similar changes are needed elsewhere. |
|
|
65
|
+
| "I understand the intent, I don't need the skill" | Understanding intent ≠ knowing the implementation. Skills define WHERE files go, WHAT format to use, and HOW to register outputs. |
|
|
66
|
+
| "The command says to load a skill, but I can handle it directly" | When a command tells you to load a skill, that is a mandatory Skill tool call, not a suggestion. |
|
|
67
|
+
| "I'll update the skill later" | Later never comes. Update before moving to the next task. |
|
|
68
|
+
|
|
69
|
+
## Failure Pattern
|
|
70
|
+
|
|
71
|
+
**Common scenario**: Task matches triggers (e.g., "spectre", "release", "learn"), but agent rationalizes skipping the skill load.
|
|
72
|
+
|
|
73
|
+
**Rationalizations that fail**: "I already have the file contents", "The error points to the exact path", "This is really about X not Y", "I can figure this out faster by searching."
|
|
74
|
+
|
|
75
|
+
**What skills provide that context doesn't**: Architectural relationships, related files you don't know about, exact workflows with registration steps, correct output paths. Partial context from Read results is not a substitute.
|
|
76
|
+
|
|
77
|
+
**The cost**: Extra tool calls, wrong output locations, missed registration steps, inconsistent changes.
|
|
78
|
+
|
|
79
|
+
## Example
|
|
80
|
+
|
|
81
|
+
User: "How does /spectre work?"
|
|
82
|
+
|
|
83
|
+
Skill list shows: `feature-spectre-plugin` with trigger `spectre`
|
|
84
|
+
|
|
85
|
+
Action: `Skill(feature-spectre-plugin)`
|
|
86
|
+
|
|
87
|
+
Then: Use the key files and patterns from that knowledge to guide your work.
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "architecture_review"
|
|
3
|
+
description: "👻 | Conduct principal architecture review"
|
|
4
|
+
user-invocable: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# architecture_review
|
|
8
|
+
|
|
9
|
+
## Input Handling
|
|
10
|
+
|
|
11
|
+
Treat the current command arguments as this workflow's input. When invoked from a slash command, use the forwarded `$ARGUMENTS` value.
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# architecture_review: Technical review of completed features
|
|
15
|
+
|
|
16
|
+
## Description
|
|
17
|
+
- **What** — Principal systems architect review focusing on compounding decisions: architectural debt, missed abstractions, performance cliffs, unnecessary complexity
|
|
18
|
+
- **Outcome** — Architecture review report with actionable findings organized by severity and type
|
|
19
|
+
|
|
20
|
+
## Variables
|
|
21
|
+
|
|
22
|
+
### Dynamic Variables
|
|
23
|
+
- `feature_description`: Feature being reviewed — (via ARGUMENTS). If
|
|
24
|
+
- `paths_or_files`: Relevant paths to examine — (via ARGUMENTS)
|
|
25
|
+
- `arch_notes_or_docs`: Existing architecture context — (via ARGUMENTS, optional)
|
|
26
|
+
|
|
27
|
+
### ARGUMENTS Input
|
|
28
|
+
|
|
29
|
+
<ARGUMENTS>
|
|
30
|
+
$ARGUMENTS
|
|
31
|
+
</ARGUMENTS>
|
|
32
|
+
|
|
33
|
+
## Instructions
|
|
34
|
+
|
|
35
|
+
**Review Philosophy** (cross-cutting guidelines):
|
|
36
|
+
- **Compounding matters**: Focus on what gets harder to change later, not what's easy to fix now
|
|
37
|
+
- **Simplicity is a feature**: The best code is often less code, fewer abstractions, fewer moving parts
|
|
38
|
+
- **Context is king**: A "bad" pattern in isolation might be the right choice given project constraints
|
|
39
|
+
- **Be specific**: Vague feedback like "could be more modular" is useless. Point to exact files, functions, and concrete alternatives
|
|
40
|
+
|
|
41
|
+
**Constraints**:
|
|
42
|
+
- Don't suggest changes that would take longer to implement than the feature itself unless they're critical
|
|
43
|
+
- Don't recommend adding abstractions "for future flexibility" unless there's concrete evidence we'll need them
|
|
44
|
+
- If you don't have concerns in a section, say "No concerns" and move on—don't manufacture feedback
|
|
45
|
+
- Be direct. "This is fine" is a valid assessment.
|
|
46
|
+
|
|
47
|
+
**Adapt**
|
|
48
|
+
- If ARGUMENTS is empty, gather the review scope from the current thread context.
|
|
49
|
+
- If the current thread context is also ambigious, ask the user to clarify the scope of the review.
|
|
50
|
+
|
|
51
|
+
## Step (1/3) - Review Existing Architecture Documents
|
|
52
|
+
- **Action** - ReviewArchitecture: Find and review existing architecture documents
|
|
53
|
+
- search for docs/architecture.md and read it if it exists
|
|
54
|
+
- if not, continue and use general architectural best practices during review
|
|
55
|
+
|
|
56
|
+
## Step (1/2) - Explore Implementation
|
|
57
|
+
|
|
58
|
+
- **Action** — ExploreCode: Thoroughly examine the implementation
|
|
59
|
+
- Read the code at `paths_or_files`
|
|
60
|
+
- Understand the data flow
|
|
61
|
+
- Trace the dependencies
|
|
62
|
+
- Review `arch_notes_or_docs` if provided
|
|
63
|
+
- **If**: Paths unclear or missing
|
|
64
|
+
- **Then**: Ask for clarification before proceeding
|
|
65
|
+
- **Else**: Continue to review
|
|
66
|
+
|
|
67
|
+
## Step (2/2) - Produce Review Report
|
|
68
|
+
|
|
69
|
+
- **Action** — GenerateReview: Create structured architecture review using Report format below
|
|
70
|
+
- Apply Review Philosophy guidelines throughout
|
|
71
|
+
- Apply Constraints (no manufactured feedback, proportionate suggestions)
|
|
72
|
+
- **If**: No concerns in a section
|
|
73
|
+
- **Then**: State "No concerns" and move on
|
|
74
|
+
- **Else**: Provide specific, actionable feedback
|
|
75
|
+
|
|
76
|
+
## Report
|
|
77
|
+
|
|
78
|
+
**Output Format** — Architecture review with these sections:
|
|
79
|
+
|
|
80
|
+
### Executive Summary
|
|
81
|
+
2-3 sentences: What's the architectural story here? Is this feature setting us up well or creating future pain?
|
|
82
|
+
|
|
83
|
+
### Critical Issues (address before moving on)
|
|
84
|
+
Issues that will cause significant pain if left unaddressed—architectural violations, major performance problems, or patterns that will spread.
|
|
85
|
+
|
|
86
|
+
For each issue:
|
|
87
|
+
- **What**: The specific problem
|
|
88
|
+
- **Where**: Exact file(s) and line(s)
|
|
89
|
+
- **Why it matters**: The compounding cost over time
|
|
90
|
+
- **Suggested fix**: Concrete, implementable alternative
|
|
91
|
+
|
|
92
|
+
### Simplification Opportunities
|
|
93
|
+
Places where we're overengineering, where a simpler approach would work, or where we've introduced abstractions we don't yet need.
|
|
94
|
+
|
|
95
|
+
### Architecture Alignment
|
|
96
|
+
- Does this follow existing project patterns, or introduce new ones?
|
|
97
|
+
- If new patterns: Are they intentional improvements or accidental divergence?
|
|
98
|
+
- Are there existing utilities/patterns in the codebase this should have used?
|
|
99
|
+
|
|
100
|
+
### Future-Proofing Considerations
|
|
101
|
+
- What assumptions is this code making that might not hold?
|
|
102
|
+
- If this feature grows 10x in usage/complexity, what breaks first?
|
|
103
|
+
- Are there integration points that need better contracts/interfaces?
|
|
104
|
+
|
|
105
|
+
### Performance Notes
|
|
106
|
+
Only mention performance if there's a clear problem or a clear win—don't speculate about micro-optimizations.
|
|
107
|
+
|
|
108
|
+
### What's Done Well
|
|
109
|
+
Briefly note architectural choices worth preserving or patterns worth spreading to other parts of the codebase.
|
|
110
|
+
|
|
111
|
+
## Success Criteria
|
|
112
|
+
|
|
113
|
+
**Step 1 - Explore Implementation**:
|
|
114
|
+
- [ ] All specified paths/files read and understood
|
|
115
|
+
- [ ] Data flow traced through implementation
|
|
116
|
+
- [ ] Dependencies identified and examined
|
|
117
|
+
- [ ] Architecture context reviewed if provided
|
|
118
|
+
|
|
119
|
+
**Step 2 - Produce Review Report**:
|
|
120
|
+
- [ ] Executive Summary provides clear architectural assessment (2-3 sentences)
|
|
121
|
+
- [ ] Critical Issues include What/Where/Why/Suggested fix for each
|
|
122
|
+
- [ ] Simplification Opportunities identify overengineering (or "No concerns")
|
|
123
|
+
- [ ] Architecture Alignment addresses pattern consistency
|
|
124
|
+
- [ ] Future-Proofing identifies assumptions and scaling concerns
|
|
125
|
+
- [ ] Performance Notes only included if clear problem/win exists
|
|
126
|
+
- [ ] What's Done Well acknowledges good patterns
|
|
127
|
+
- [ ] All feedback is specific with exact files/lines
|
|
128
|
+
- [ ] No manufactured feedback—"No concerns" used when appropriate
|
|
129
|
+
- [ ] Suggestions proportionate to feature scope
|