@itz4blitz/agentful 1.2.0 → 1.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/README.md +28 -1
- package/bin/cli.js +11 -1055
- package/bin/hooks/block-file-creation.js +271 -0
- package/bin/hooks/product-spec-watcher.js +151 -0
- package/lib/index.js +0 -11
- package/lib/init.js +2 -21
- package/lib/parallel-execution.js +235 -0
- package/lib/presets.js +26 -4
- package/package.json +4 -7
- package/template/.claude/agents/architect.md +2 -2
- package/template/.claude/agents/backend.md +17 -30
- package/template/.claude/agents/frontend.md +17 -39
- package/template/.claude/agents/orchestrator.md +63 -4
- package/template/.claude/agents/product-analyzer.md +1 -1
- package/template/.claude/agents/tester.md +16 -29
- package/template/.claude/commands/agentful-generate.md +221 -14
- package/template/.claude/commands/agentful-init.md +621 -0
- package/template/.claude/commands/agentful-product.md +1 -1
- package/template/.claude/commands/agentful-start.md +99 -1
- package/template/.claude/product/EXAMPLES.md +2 -2
- package/template/.claude/product/index.md +1 -1
- package/template/.claude/settings.json +22 -0
- package/template/.claude/skills/research/SKILL.md +432 -0
- package/template/CLAUDE.md +5 -6
- package/template/bin/hooks/architect-drift-detector.js +242 -0
- package/template/bin/hooks/product-spec-watcher.js +151 -0
- package/version.json +1 -1
- package/bin/hooks/post-agent.js +0 -101
- package/bin/hooks/post-feature.js +0 -227
- package/bin/hooks/pre-agent.js +0 -118
- package/bin/hooks/pre-feature.js +0 -138
- package/lib/VALIDATION_README.md +0 -455
- package/lib/ci/claude-action-integration.js +0 -641
- package/lib/ci/index.js +0 -10
- package/lib/core/analyzer.js +0 -497
- package/lib/core/cli.js +0 -141
- package/lib/core/detectors/conventions.js +0 -342
- package/lib/core/detectors/framework.js +0 -276
- package/lib/core/detectors/index.js +0 -15
- package/lib/core/detectors/language.js +0 -199
- package/lib/core/detectors/patterns.js +0 -356
- package/lib/core/generator.js +0 -626
- package/lib/core/index.js +0 -9
- package/lib/core/output-parser.js +0 -458
- package/lib/core/storage.js +0 -515
- package/lib/core/templates.js +0 -556
- package/lib/pipeline/cli.js +0 -423
- package/lib/pipeline/engine.js +0 -928
- package/lib/pipeline/executor.js +0 -440
- package/lib/pipeline/index.js +0 -33
- package/lib/pipeline/integrations.js +0 -559
- package/lib/pipeline/schemas.js +0 -288
- package/lib/remote/client.js +0 -361
- package/lib/server/auth.js +0 -270
- package/lib/server/client-example.js +0 -190
- package/lib/server/executor.js +0 -477
- package/lib/server/index.js +0 -494
- package/lib/update-helpers.js +0 -505
- package/lib/validation.js +0 -460
package/lib/core/templates.js
DELETED
|
@@ -1,556 +0,0 @@
|
|
|
1
|
-
import fs from 'fs/promises';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import { fileURLToPath } from 'url';
|
|
4
|
-
|
|
5
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Template Manager
|
|
9
|
-
*
|
|
10
|
-
* Manages agent templates with support for:
|
|
11
|
-
* - Base templates (orchestrator, backend, frontend, etc.)
|
|
12
|
-
* - Framework-specific templates (Next.js, NestJS, etc.)
|
|
13
|
-
* - Pattern templates (database, auth, etc.)
|
|
14
|
-
* - Custom user templates
|
|
15
|
-
* - Template inheritance
|
|
16
|
-
*
|
|
17
|
-
* Templates are organized in:
|
|
18
|
-
* - templates/base/ - Core agent templates
|
|
19
|
-
* - templates/frameworks/ - Framework-specific templates
|
|
20
|
-
* - templates/patterns/ - Pattern-based templates
|
|
21
|
-
* - .agentful/templates/custom/ - User custom templates
|
|
22
|
-
*/
|
|
23
|
-
export class TemplateManager {
|
|
24
|
-
constructor(projectPath, templateBaseDir = null) {
|
|
25
|
-
this.projectPath = projectPath;
|
|
26
|
-
this.templateBaseDir = templateBaseDir || path.join(__dirname, '../../templates');
|
|
27
|
-
this.customTemplateDir = path.join(projectPath, '.agentful', 'templates', 'custom');
|
|
28
|
-
this.cache = new Map();
|
|
29
|
-
this.registry = new Map();
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Initialize template system
|
|
34
|
-
*/
|
|
35
|
-
async initialize() {
|
|
36
|
-
await this._ensureDirectories();
|
|
37
|
-
await this._loadBuiltInTemplates();
|
|
38
|
-
await this._scanTemplates();
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Load template by name or path
|
|
43
|
-
*
|
|
44
|
-
* @param {string} nameOrPath - Template name (e.g., 'base/backend') or path
|
|
45
|
-
* @returns {Promise<string>} Template content
|
|
46
|
-
*/
|
|
47
|
-
async loadTemplate(nameOrPath) {
|
|
48
|
-
// Check cache first
|
|
49
|
-
if (this.cache.has(nameOrPath)) {
|
|
50
|
-
return this.cache.get(nameOrPath);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// Find template file
|
|
54
|
-
const templatePath = await this._findTemplatePath(nameOrPath);
|
|
55
|
-
if (!templatePath) {
|
|
56
|
-
throw new Error(`Template not found: ${nameOrPath}`);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// Load template content
|
|
60
|
-
const content = await fs.readFile(templatePath, 'utf-8');
|
|
61
|
-
|
|
62
|
-
// Handle template inheritance (if template has "extends" directive)
|
|
63
|
-
const extendedContent = await this._processInheritance(content);
|
|
64
|
-
|
|
65
|
-
// Cache the template
|
|
66
|
-
this.cache.set(nameOrPath, extendedContent);
|
|
67
|
-
|
|
68
|
-
return extendedContent;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* List all available templates
|
|
73
|
-
*
|
|
74
|
-
* @returns {Promise<Array>} Template metadata
|
|
75
|
-
*/
|
|
76
|
-
async listTemplates() {
|
|
77
|
-
return Array.from(this.registry.values());
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Find templates by criteria
|
|
82
|
-
*
|
|
83
|
-
* @param {Object} criteria - Search criteria
|
|
84
|
-
* @param {string} criteria.type - Template type (base, framework, pattern)
|
|
85
|
-
* @param {string} criteria.category - Template category
|
|
86
|
-
* @param {Array} criteria.tags - Template tags
|
|
87
|
-
* @returns {Promise<Array>} Matching templates
|
|
88
|
-
*/
|
|
89
|
-
async findTemplates(criteria = {}) {
|
|
90
|
-
const matching = [];
|
|
91
|
-
|
|
92
|
-
for (const [name, meta] of this.registry) {
|
|
93
|
-
let matches = true;
|
|
94
|
-
|
|
95
|
-
if (criteria.type && meta.type !== criteria.type) {
|
|
96
|
-
matches = false;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
if (criteria.category && meta.category !== criteria.category) {
|
|
100
|
-
matches = false;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
if (criteria.tags && criteria.tags.length > 0) {
|
|
104
|
-
const hasTag = criteria.tags.some(tag => meta.tags?.includes(tag));
|
|
105
|
-
if (!hasTag) {
|
|
106
|
-
matches = false;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
if (matches) {
|
|
111
|
-
matching.push({ name, ...meta });
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
return matching;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* Create custom template
|
|
120
|
-
*
|
|
121
|
-
* @param {string} name - Template name
|
|
122
|
-
* @param {string} content - Template content
|
|
123
|
-
* @param {Object} metadata - Template metadata
|
|
124
|
-
*/
|
|
125
|
-
async createTemplate(name, content, metadata = {}) {
|
|
126
|
-
const templatePath = path.join(this.customTemplateDir, `${name}.md`);
|
|
127
|
-
|
|
128
|
-
// Ensure custom template directory exists
|
|
129
|
-
await fs.mkdir(this.customTemplateDir, { recursive: true });
|
|
130
|
-
|
|
131
|
-
// Write template
|
|
132
|
-
await fs.writeFile(templatePath, content, 'utf-8');
|
|
133
|
-
|
|
134
|
-
// Update registry
|
|
135
|
-
this.registry.set(name, {
|
|
136
|
-
type: 'custom',
|
|
137
|
-
category: metadata.category || 'custom',
|
|
138
|
-
tags: metadata.tags || [],
|
|
139
|
-
path: templatePath,
|
|
140
|
-
...metadata
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
// Invalidate cache
|
|
144
|
-
this.cache.delete(name);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* Find template file path
|
|
149
|
-
*
|
|
150
|
-
* @param {string} nameOrPath - Template name or path
|
|
151
|
-
* @returns {Promise<string|null>} Template path or null
|
|
152
|
-
* @private
|
|
153
|
-
*/
|
|
154
|
-
async _findTemplatePath(nameOrPath) {
|
|
155
|
-
// If it's a relative path with slashes, search in that category
|
|
156
|
-
if (nameOrPath.includes('/')) {
|
|
157
|
-
const [category, name] = nameOrPath.split('/');
|
|
158
|
-
const searchPaths = [
|
|
159
|
-
path.join(this.templateBaseDir, category, `${name}.md`),
|
|
160
|
-
path.join(this.customTemplateDir, nameOrPath, `${name}.md`)
|
|
161
|
-
];
|
|
162
|
-
|
|
163
|
-
for (const searchPath of searchPaths) {
|
|
164
|
-
try {
|
|
165
|
-
await fs.access(searchPath);
|
|
166
|
-
return searchPath;
|
|
167
|
-
} catch {
|
|
168
|
-
// Continue searching
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
// Search in all template directories
|
|
174
|
-
const searchPaths = [
|
|
175
|
-
path.join(this.customTemplateDir, `${nameOrPath}.md`),
|
|
176
|
-
path.join(this.templateBaseDir, 'frameworks', `${nameOrPath}.md`),
|
|
177
|
-
path.join(this.templateBaseDir, 'patterns', `${nameOrPath}.md`),
|
|
178
|
-
path.join(this.templateBaseDir, 'base', `${nameOrPath}.md`)
|
|
179
|
-
];
|
|
180
|
-
|
|
181
|
-
for (const searchPath of searchPaths) {
|
|
182
|
-
try {
|
|
183
|
-
await fs.access(searchPath);
|
|
184
|
-
return searchPath;
|
|
185
|
-
} catch {
|
|
186
|
-
// Continue searching
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
return null;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
/**
|
|
194
|
-
* Process template inheritance
|
|
195
|
-
*
|
|
196
|
-
* @param {string} content - Template content
|
|
197
|
-
* @returns {Promise<string>} Extended content
|
|
198
|
-
* @private
|
|
199
|
-
*/
|
|
200
|
-
async _processInheritance(content) {
|
|
201
|
-
// Check for extends directive in frontmatter
|
|
202
|
-
const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
203
|
-
if (!frontmatterMatch) {
|
|
204
|
-
return content;
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
const frontmatter = frontmatterMatch[1];
|
|
208
|
-
const extendsMatch = frontmatter.match(/extends:\s*(.+)/);
|
|
209
|
-
|
|
210
|
-
if (!extendsMatch) {
|
|
211
|
-
return content;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
const parentTemplate = extendsMatch[1].trim();
|
|
215
|
-
|
|
216
|
-
// Load parent template
|
|
217
|
-
const parentContent = await this.loadTemplate(parentTemplate);
|
|
218
|
-
|
|
219
|
-
// Merge templates (simple approach: parent + child sections)
|
|
220
|
-
return this._mergeTemplates(parentContent, content);
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
/**
|
|
224
|
-
* Merge parent and child templates
|
|
225
|
-
*
|
|
226
|
-
* @param {string} parent - Parent template content
|
|
227
|
-
* @param {string} child - Child template content
|
|
228
|
-
* @returns {string} Merged content
|
|
229
|
-
* @private
|
|
230
|
-
*/
|
|
231
|
-
_mergeTemplates(parent, child) {
|
|
232
|
-
// Extract frontmatter from both
|
|
233
|
-
const parentFrontmatter = parent.match(/^---\n([\s\S]*?)\n---/)?.[1] || '';
|
|
234
|
-
const childFrontmatter = child.match(/^---\n([\s\S]*?)\n---/)?.[1] || '';
|
|
235
|
-
|
|
236
|
-
// Extract body (everything after frontmatter)
|
|
237
|
-
const parentBody = parent.replace(/^---\n[\s\S]*?\n---\n?/, '');
|
|
238
|
-
const childBody = child.replace(/^---\n[\s\S]*?\n---\n?/, '');
|
|
239
|
-
|
|
240
|
-
// Merge frontmatter (child overrides parent)
|
|
241
|
-
const mergedFrontmatter = this._mergeFrontmatter(parentFrontmatter, childFrontmatter);
|
|
242
|
-
|
|
243
|
-
// Merge body (append child sections to parent)
|
|
244
|
-
const mergedBody = parentBody + '\n\n' + childBody;
|
|
245
|
-
|
|
246
|
-
return `---\n${mergedFrontmatter}\n---\n\n${mergedBody}`;
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
/**
|
|
250
|
-
* Merge frontmatter YAML
|
|
251
|
-
*
|
|
252
|
-
* @param {string} parent - Parent frontmatter
|
|
253
|
-
* @param {string} child - Child frontmatter
|
|
254
|
-
* @returns {string} Merged frontmatter
|
|
255
|
-
* @private
|
|
256
|
-
*/
|
|
257
|
-
_mergeFrontmatter(parent, child) {
|
|
258
|
-
const parseYaml = (yaml) => {
|
|
259
|
-
const obj = {};
|
|
260
|
-
const lines = yaml.split('\n');
|
|
261
|
-
|
|
262
|
-
for (const line of lines) {
|
|
263
|
-
const match = line.match(/^(\w+):\s*(.+)$/);
|
|
264
|
-
if (match) {
|
|
265
|
-
const [, key, value] = match;
|
|
266
|
-
obj[key] = value.trim();
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
return obj;
|
|
271
|
-
};
|
|
272
|
-
|
|
273
|
-
const parentObj = parseYaml(parent);
|
|
274
|
-
const childObj = parseYaml(child);
|
|
275
|
-
|
|
276
|
-
// Merge objects (child overrides parent)
|
|
277
|
-
const merged = { ...parentObj, ...childObj };
|
|
278
|
-
|
|
279
|
-
// Convert back to YAML
|
|
280
|
-
return Object.entries(merged)
|
|
281
|
-
.map(([key, value]) => `${key}: ${value}`)
|
|
282
|
-
.join('\n');
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
/**
|
|
286
|
-
* Ensure template directories exist
|
|
287
|
-
*
|
|
288
|
-
* @private
|
|
289
|
-
*/
|
|
290
|
-
async _ensureDirectories() {
|
|
291
|
-
const dirs = [
|
|
292
|
-
path.join(this.templateBaseDir, 'base'),
|
|
293
|
-
path.join(this.templateBaseDir, 'frameworks'),
|
|
294
|
-
path.join(this.templateBaseDir, 'patterns'),
|
|
295
|
-
this.customTemplateDir
|
|
296
|
-
];
|
|
297
|
-
|
|
298
|
-
for (const dir of dirs) {
|
|
299
|
-
await fs.mkdir(dir, { recursive: true });
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
/**
|
|
304
|
-
* Load built-in templates
|
|
305
|
-
*
|
|
306
|
-
* @private
|
|
307
|
-
*/
|
|
308
|
-
async _loadBuiltInTemplates() {
|
|
309
|
-
// Create base templates if they don't exist
|
|
310
|
-
const baseTemplates = this._getBuiltInTemplates();
|
|
311
|
-
|
|
312
|
-
for (const [name, content] of Object.entries(baseTemplates)) {
|
|
313
|
-
const templatePath = path.join(this.templateBaseDir, 'base', `${name}.md`);
|
|
314
|
-
|
|
315
|
-
try {
|
|
316
|
-
await fs.access(templatePath);
|
|
317
|
-
// Template exists, don't overwrite
|
|
318
|
-
} catch {
|
|
319
|
-
// Template doesn't exist, create it
|
|
320
|
-
await fs.writeFile(templatePath, content, 'utf-8');
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
/**
|
|
326
|
-
* Scan all templates and build registry
|
|
327
|
-
*
|
|
328
|
-
* @private
|
|
329
|
-
*/
|
|
330
|
-
async _scanTemplates() {
|
|
331
|
-
const categories = [
|
|
332
|
-
{ dir: path.join(this.templateBaseDir, 'base'), type: 'base' },
|
|
333
|
-
{ dir: path.join(this.templateBaseDir, 'frameworks'), type: 'framework' },
|
|
334
|
-
{ dir: path.join(this.templateBaseDir, 'patterns'), type: 'pattern' },
|
|
335
|
-
{ dir: this.customTemplateDir, type: 'custom' }
|
|
336
|
-
];
|
|
337
|
-
|
|
338
|
-
for (const { dir, type } of categories) {
|
|
339
|
-
try {
|
|
340
|
-
const files = await fs.readdir(dir);
|
|
341
|
-
|
|
342
|
-
for (const file of files) {
|
|
343
|
-
if (file.endsWith('.md')) {
|
|
344
|
-
const name = path.basename(file, '.md');
|
|
345
|
-
const filePath = path.join(dir, file);
|
|
346
|
-
|
|
347
|
-
// Extract metadata from frontmatter
|
|
348
|
-
const content = await fs.readFile(filePath, 'utf-8');
|
|
349
|
-
const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
350
|
-
|
|
351
|
-
if (frontmatterMatch) {
|
|
352
|
-
const frontmatter = frontmatterMatch[1];
|
|
353
|
-
const metadata = this._parseFrontmatter(frontmatter);
|
|
354
|
-
|
|
355
|
-
this.registry.set(name, {
|
|
356
|
-
type,
|
|
357
|
-
category: metadata.category || type,
|
|
358
|
-
tags: metadata.tags || [],
|
|
359
|
-
description: metadata.description,
|
|
360
|
-
path: filePath
|
|
361
|
-
});
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
} catch (error) {
|
|
366
|
-
// Directory doesn't exist, skip
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
/**
|
|
372
|
-
* Parse frontmatter YAML
|
|
373
|
-
*
|
|
374
|
-
* @param {string} frontmatter - Frontmatter content
|
|
375
|
-
* @returns {Object} Parsed metadata
|
|
376
|
-
* @private
|
|
377
|
-
*/
|
|
378
|
-
_parseFrontmatter(frontmatter) {
|
|
379
|
-
const metadata = {};
|
|
380
|
-
const lines = frontmatter.split('\n');
|
|
381
|
-
|
|
382
|
-
for (const line of lines) {
|
|
383
|
-
const match = line.match(/^(\w+):\s*(.+)$/);
|
|
384
|
-
if (match) {
|
|
385
|
-
const [, key, value] = match;
|
|
386
|
-
metadata[key] = value.trim();
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
return metadata;
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
/**
|
|
394
|
-
* Get built-in template content
|
|
395
|
-
*
|
|
396
|
-
* @returns {Object} Template name -> content mapping
|
|
397
|
-
* @private
|
|
398
|
-
*/
|
|
399
|
-
_getBuiltInTemplates() {
|
|
400
|
-
return {
|
|
401
|
-
orchestrator: `---
|
|
402
|
-
name: orchestrator
|
|
403
|
-
description: Coordinates structured product development with human checkpoints
|
|
404
|
-
model: opus
|
|
405
|
-
tools: Read, Write, Edit, Glob, Grep, Task
|
|
406
|
-
category: base
|
|
407
|
-
tags: core, orchestration
|
|
408
|
-
---
|
|
409
|
-
|
|
410
|
-
# {{projectName}} Orchestrator
|
|
411
|
-
|
|
412
|
-
You coordinate autonomous product development for **{{projectName}}**.
|
|
413
|
-
|
|
414
|
-
## Tech Stack
|
|
415
|
-
|
|
416
|
-
{{#if techStack}}
|
|
417
|
-
{{#each techStack}}
|
|
418
|
-
- **{{@key}}**: {{this}}
|
|
419
|
-
{{/each}}
|
|
420
|
-
{{/if}}
|
|
421
|
-
|
|
422
|
-
## Your Role
|
|
423
|
-
|
|
424
|
-
You orchestrate all development activities by delegating to specialized agents.
|
|
425
|
-
|
|
426
|
-
## Workflow
|
|
427
|
-
|
|
428
|
-
1. Analyze requirements from product spec
|
|
429
|
-
2. Delegate architecture to @architect
|
|
430
|
-
3. Delegate implementation to specialist agents
|
|
431
|
-
4. Coordinate validation with @reviewer
|
|
432
|
-
5. Delegate fixes to @fixer
|
|
433
|
-
6. Track progress in state.json
|
|
434
|
-
`,
|
|
435
|
-
|
|
436
|
-
backend: `---
|
|
437
|
-
name: backend
|
|
438
|
-
description: Implements backend services, APIs, databases, and business logic
|
|
439
|
-
model: sonnet
|
|
440
|
-
tools: Read, Write, Edit, Glob, Grep, Bash
|
|
441
|
-
category: base
|
|
442
|
-
tags: backend, api, database
|
|
443
|
-
---
|
|
444
|
-
|
|
445
|
-
# {{projectName}} Backend Agent
|
|
446
|
-
|
|
447
|
-
You implement server-side code for **{{projectName}}** using {{#if framework}}{{framework}}{{else}}best practices{{/if}}.
|
|
448
|
-
|
|
449
|
-
## Tech Stack
|
|
450
|
-
|
|
451
|
-
- **Language**: {{language}}
|
|
452
|
-
{{#if framework}}- **Framework**: {{framework}}{{/if}}
|
|
453
|
-
{{#if database}}- **Database**: {{database.type}}{{/if}}
|
|
454
|
-
{{#if orm}}- **ORM**: {{orm}}{{/if}}
|
|
455
|
-
|
|
456
|
-
## Your Scope
|
|
457
|
-
|
|
458
|
-
- API Routes & Controllers
|
|
459
|
-
- Service Layer (business logic)
|
|
460
|
-
- Repository Layer (data access)
|
|
461
|
-
- Database schemas and migrations
|
|
462
|
-
- Authentication & Authorization
|
|
463
|
-
- Input validation
|
|
464
|
-
- Error handling
|
|
465
|
-
- Caching strategies
|
|
466
|
-
|
|
467
|
-
## Architecture Pattern
|
|
468
|
-
|
|
469
|
-
Follow clean architecture with three layers:
|
|
470
|
-
|
|
471
|
-
1. **Controllers** - Handle HTTP requests/responses
|
|
472
|
-
2. **Services** - Business logic and orchestration
|
|
473
|
-
3. **Repositories** - Data access and external services
|
|
474
|
-
|
|
475
|
-
See \`.claude/skills/backend-patterns/SKILL.md\` for detailed implementation patterns.
|
|
476
|
-
|
|
477
|
-
## Boundaries
|
|
478
|
-
|
|
479
|
-
### Handles
|
|
480
|
-
- Server-side business logic
|
|
481
|
-
- API endpoint implementation
|
|
482
|
-
- Database operations
|
|
483
|
-
- Authentication flows
|
|
484
|
-
|
|
485
|
-
### Delegates to @frontend
|
|
486
|
-
- UI components, client-side state
|
|
487
|
-
|
|
488
|
-
### Delegates to @tester
|
|
489
|
-
- Unit tests, integration tests
|
|
490
|
-
|
|
491
|
-
## Rules
|
|
492
|
-
|
|
493
|
-
1. **Always validate inputs** - Never trust client data
|
|
494
|
-
2. **Use transactions** - Multi-step DB operations must be atomic
|
|
495
|
-
3. **Handle errors properly** - Return meaningful error messages
|
|
496
|
-
4. **Follow project patterns** - Match existing code conventions
|
|
497
|
-
`,
|
|
498
|
-
|
|
499
|
-
frontend: `---
|
|
500
|
-
name: frontend
|
|
501
|
-
description: Implements UI components, pages, and client-side logic
|
|
502
|
-
model: sonnet
|
|
503
|
-
tools: Read, Write, Edit, Glob, Grep, Bash
|
|
504
|
-
category: base
|
|
505
|
-
tags: frontend, ui, components
|
|
506
|
-
---
|
|
507
|
-
|
|
508
|
-
# {{projectName}} Frontend Agent
|
|
509
|
-
|
|
510
|
-
You implement client-side code for **{{projectName}}** using {{#if framework}}{{framework}}{{else}}modern web standards{{/if}}.
|
|
511
|
-
|
|
512
|
-
## Tech Stack
|
|
513
|
-
|
|
514
|
-
- **Language**: {{language}}
|
|
515
|
-
{{#if framework}}- **Framework**: {{framework}}{{/if}}
|
|
516
|
-
- **Styling**: {{#if styling}}{{styling}}{{else}}CSS{{/if}}
|
|
517
|
-
|
|
518
|
-
## Your Scope
|
|
519
|
-
|
|
520
|
-
- UI Components
|
|
521
|
-
- Pages and Routes
|
|
522
|
-
- State Management
|
|
523
|
-
- API Integration
|
|
524
|
-
- Form Validation
|
|
525
|
-
- Client-side Routing
|
|
526
|
-
- Responsive Design
|
|
527
|
-
- Accessibility
|
|
528
|
-
|
|
529
|
-
See \`.claude/skills/frontend-patterns/SKILL.md\` for detailed implementation patterns.
|
|
530
|
-
|
|
531
|
-
## Boundaries
|
|
532
|
-
|
|
533
|
-
### Handles
|
|
534
|
-
- Client-side UI and interactions
|
|
535
|
-
- Component architecture
|
|
536
|
-
- State management
|
|
537
|
-
- Form handling
|
|
538
|
-
|
|
539
|
-
### Delegates to @backend
|
|
540
|
-
- API endpoints, business logic
|
|
541
|
-
|
|
542
|
-
### Delegates to @tester
|
|
543
|
-
- Component tests, E2E tests
|
|
544
|
-
|
|
545
|
-
## Rules
|
|
546
|
-
|
|
547
|
-
1. **Semantic HTML** - Use proper HTML5 elements
|
|
548
|
-
2. **Accessibility first** - WCAG 2.1 AA compliance
|
|
549
|
-
3. **Responsive design** - Mobile-first approach
|
|
550
|
-
4. **Performance** - Optimize bundle size and rendering
|
|
551
|
-
`
|
|
552
|
-
};
|
|
553
|
-
}
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
export default TemplateManager;
|