cast-code 1.0.5 → 1.0.6
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/dist/modules/git/services/pr-generator.service.js +70 -69
- package/dist/modules/git/services/pr-generator.service.js.map +1 -1
- package/package.json +1 -1
- package/dist/modules/agents/definitions/architect.md +0 -35
- package/dist/modules/agents/definitions/backend.md +0 -43
- package/dist/modules/agents/definitions/coder.md +0 -34
- package/dist/modules/agents/definitions/devops.md +0 -42
- package/dist/modules/agents/definitions/frontend.md +0 -46
- package/dist/modules/agents/definitions/reviewer.md +0 -35
- package/dist/modules/agents/definitions/tester.md +0 -41
- package/dist/modules/skills/definitions/general/file-operations.md +0 -60
- package/dist/modules/skills/definitions/general/git-operations.md +0 -59
- package/dist/modules/skills/definitions/general/planning.md +0 -86
- package/dist/modules/skills/definitions/general/search.md +0 -59
- package/dist/modules/skills/definitions/specialized/api-design.md +0 -85
- package/dist/modules/skills/definitions/specialized/database-operations.md +0 -78
- package/dist/modules/skills/definitions/specialized/frontend-bootstrap.md +0 -71
- package/dist/modules/skills/definitions/specialized/react-patterns.md +0 -77
- package/dist/modules/skills/definitions/specialized/testing-strategies.md +0 -79
|
@@ -170,7 +170,7 @@ let PrGeneratorService = class PrGeneratorService {
|
|
|
170
170
|
const { title, description, commitSummaries } = this.parseSingleResponse(content, commits);
|
|
171
171
|
return {
|
|
172
172
|
title: title || this.generateDefaultTitle(branchName),
|
|
173
|
-
description,
|
|
173
|
+
description: description && description.trim().length > 0 ? description : this.getPRTemplate(),
|
|
174
174
|
commits: commitSummaries
|
|
175
175
|
};
|
|
176
176
|
}
|
|
@@ -263,7 +263,7 @@ let PrGeneratorService = class PrGeneratorService {
|
|
|
263
263
|
}
|
|
264
264
|
}
|
|
265
265
|
formatPRForClipboard(title, description, baseBranch) {
|
|
266
|
-
return
|
|
266
|
+
return description;
|
|
267
267
|
}
|
|
268
268
|
getPRCreateUrl(platform, baseBranch) {
|
|
269
269
|
try {
|
|
@@ -294,16 +294,9 @@ let PrGeneratorService = class PrGeneratorService {
|
|
|
294
294
|
const scope = this.monorepoDetector.determineScope(commit.files, monorepoInfo);
|
|
295
295
|
return `Analyze this commit:\n\n**Commit:** ${commit.hash}\n**Message:** ${commit.message}\n**Author:** ${commit.author}\n**Date:** ${commit.date}\n**Scope:** ${scope || 'general'}\n\n**Files Changed:**\n${commit.files.join('\n')}\n\n**Diff Stats:**\n${commit.diff}\n\nProvide:\n1. A one-line summary (max 100 chars)\n2. Detailed explanation of changes, approach, and impact`;
|
|
296
296
|
}
|
|
297
|
-
buildPRDescriptionPrompt(branchName, commits, baseBranch) {
|
|
298
|
-
const commitsSummary = commits.map((c, i)=>`${i + 1}. **${c.hash}** - ${c.summary}\n ${c.details.slice(0, 200)}...`).join('\n\n');
|
|
299
|
-
return `Create a PR description for branch "${branchName}" to "${baseBranch}".\n\n**Commits:**\n${commitsSummary}\n\nGenerate:\n1. PR title (use branch name as inspiration)\n2. Description with: Overview, Changes, Technical Details, Testing`;
|
|
300
|
-
}
|
|
301
297
|
getCommitAnalysisSystemPrompt() {
|
|
302
298
|
return `Analyze a git commit. Provide:\n\n1. **Summary**: One sentence (max 100 chars)\n2. **Details**: Detailed paragraph about changes\n\nFormat:\nSUMMARY: <summary>\n\nDETAILS: <details>`;
|
|
303
299
|
}
|
|
304
|
-
getPRDescriptionSystemPrompt() {
|
|
305
|
-
return `Create a Pull Request description.\n\n**Title:** Concise, descriptive\n\n**Description Structure:**\n\`\`\`markdown\n## Overview\nBrief explanation\n\n## Changes\n- Change 1\n- Change 2\n\n## Technical Details\nImplementation details\n\n## Testing\nHow to test\n\`\`\``;
|
|
306
|
-
}
|
|
307
300
|
parseCommitAnalysis(content) {
|
|
308
301
|
const summaryMatch = content.match(/SUMMARY:\s*(.+?)(?=\n\n|DETAILS:|$)/is);
|
|
309
302
|
const detailsMatch = content.match(/DETAILS:\s*(.+?)$/is);
|
|
@@ -327,71 +320,37 @@ let PrGeneratorService = class PrGeneratorService {
|
|
|
327
320
|
return `Branch: ${branchName}\nBase: ${baseBranch}\nCommits: ${commits.length}\n\n${commitsInfo}`;
|
|
328
321
|
}
|
|
329
322
|
getSingleAgentSystemPrompt() {
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
**OUTPUT FORMAT:**
|
|
333
|
-
TITLE: <PR title based on branch name and overall changes>
|
|
334
|
-
|
|
335
|
-
OVERVIEW: <2-3 sentences explaining what this PR accomplishes>
|
|
336
|
-
|
|
337
|
-
CHANGES:
|
|
338
|
-
- <key change 1>
|
|
339
|
-
- <key change 2>
|
|
340
|
-
- ...
|
|
341
|
-
|
|
342
|
-
TECHNICAL_DETAILS: <important implementation details, architecture decisions>
|
|
323
|
+
const template = this.getPRTemplate();
|
|
324
|
+
return `You are a senior developer creating a Pull Request description. Analyze ALL commits and fill in the PR template below.
|
|
343
325
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
326
|
+
Rules:
|
|
327
|
+
- Output ONLY the filled template.
|
|
328
|
+
- Keep headings, checklists, and ordering exactly as shown.
|
|
329
|
+
- Fill ONLY these sections with content: "O que essa PR faz?", "O que foi mexido?", "O que eu fiz?".
|
|
330
|
+
- Leave the other sections blank for the user to fill in.
|
|
331
|
+
- Do not add any extra sections beyond the template.
|
|
332
|
+
- Keep the final reminder line.
|
|
347
333
|
|
|
348
|
-
|
|
334
|
+
PR TEMPLATE:
|
|
335
|
+
${template}`;
|
|
349
336
|
}
|
|
350
337
|
parseSingleResponse(content, commits) {
|
|
351
|
-
const
|
|
352
|
-
|
|
353
|
-
const
|
|
354
|
-
const
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
if (overviewMatch) {
|
|
360
|
-
parts.push('## Overview\n' + overviewMatch[1].trim());
|
|
338
|
+
const title = '';
|
|
339
|
+
let description = content.trim();
|
|
340
|
+
const requiredHeading = '## 🚀 O que essa PR faz?';
|
|
341
|
+
const hasRequiredHeading = description.includes(requiredHeading);
|
|
342
|
+
if (!hasRequiredHeading) {
|
|
343
|
+
description = this.getPRTemplate();
|
|
344
|
+
} else if (!description.includes('Não se esqueça de revisar essa descrição')) {
|
|
345
|
+
description = `${description.trim()}\n\nNão se esqueça de revisar essa descrição`;
|
|
361
346
|
}
|
|
362
|
-
if (changesMatch) {
|
|
363
|
-
parts.push('## Changes\n' + changesMatch[1].trim());
|
|
364
|
-
}
|
|
365
|
-
if (technicalMatch) {
|
|
366
|
-
parts.push('## Technical Details\n' + technicalMatch[1].trim());
|
|
367
|
-
}
|
|
368
|
-
if (testingMatch) {
|
|
369
|
-
parts.push('## Testing\n' + testingMatch[1].trim());
|
|
370
|
-
}
|
|
371
|
-
const description = parts.join('\n\n');
|
|
372
347
|
const commitSummaries = [];
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
commitSummaries.push({
|
|
380
|
-
hash: match[1].slice(0, 7),
|
|
381
|
-
summary: match[2].trim(),
|
|
382
|
-
details: ''
|
|
383
|
-
});
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
if (commitSummaries.length === 0) {
|
|
388
|
-
for (const commit of commits){
|
|
389
|
-
commitSummaries.push({
|
|
390
|
-
hash: commit.hash,
|
|
391
|
-
summary: commit.message.slice(0, 60),
|
|
392
|
-
details: ''
|
|
393
|
-
});
|
|
394
|
-
}
|
|
348
|
+
for (const commit of commits){
|
|
349
|
+
commitSummaries.push({
|
|
350
|
+
hash: commit.hash,
|
|
351
|
+
summary: commit.message.slice(0, 60),
|
|
352
|
+
details: ''
|
|
353
|
+
});
|
|
395
354
|
}
|
|
396
355
|
return {
|
|
397
356
|
title,
|
|
@@ -400,7 +359,7 @@ TESTING: <how to test these changes>`;
|
|
|
400
359
|
};
|
|
401
360
|
}
|
|
402
361
|
generateDefaultTitle(branchName) {
|
|
403
|
-
return branchName
|
|
362
|
+
return branchName;
|
|
404
363
|
}
|
|
405
364
|
extractContent(content) {
|
|
406
365
|
if (typeof content === 'string') return content;
|
|
@@ -412,9 +371,51 @@ TESTING: <how to test these changes>`;
|
|
|
412
371
|
}
|
|
413
372
|
return String(content);
|
|
414
373
|
}
|
|
374
|
+
getPRTemplate() {
|
|
375
|
+
if (this.prTemplateCache) {
|
|
376
|
+
return this.prTemplateCache;
|
|
377
|
+
}
|
|
378
|
+
try {
|
|
379
|
+
const fs = require('fs');
|
|
380
|
+
const raw = fs.readFileSync(this.prTemplatePath, 'utf-8').trimEnd();
|
|
381
|
+
this.prTemplateCache = this.normalizeTemplate(raw);
|
|
382
|
+
return this.prTemplateCache;
|
|
383
|
+
} catch {
|
|
384
|
+
const fallback = this.buildDefaultTemplate();
|
|
385
|
+
this.prTemplateCache = fallback;
|
|
386
|
+
return this.prTemplateCache;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
normalizeTemplate(raw) {
|
|
390
|
+
const trimmed = raw.trimEnd();
|
|
391
|
+
if (trimmed.includes('Não se esqueça de revisar essa descrição')) {
|
|
392
|
+
return trimmed;
|
|
393
|
+
}
|
|
394
|
+
return `${trimmed}\n\nNão se esqueça de revisar essa descrição`;
|
|
395
|
+
}
|
|
396
|
+
buildDefaultTemplate() {
|
|
397
|
+
return [
|
|
398
|
+
'## 🚀 O que essa PR faz?',
|
|
399
|
+
'',
|
|
400
|
+
'## 🛠️ O que foi mexido?',
|
|
401
|
+
'',
|
|
402
|
+
'## 💡 O que eu fiz? (Resumo técnico)',
|
|
403
|
+
'',
|
|
404
|
+
'## 🧪 Como testar?',
|
|
405
|
+
'',
|
|
406
|
+
'## ✅ Checklist do Dev',
|
|
407
|
+
'',
|
|
408
|
+
'## 📸 Prints / GIFs (Se for UI)',
|
|
409
|
+
'',
|
|
410
|
+
'## 🔗 Link da Task',
|
|
411
|
+
'',
|
|
412
|
+
'Não se esqueça de revisar essa descrição'
|
|
413
|
+
].join('\n');
|
|
414
|
+
}
|
|
415
415
|
constructor(multiLlmService, monorepoDetector){
|
|
416
416
|
this.multiLlmService = multiLlmService;
|
|
417
417
|
this.monorepoDetector = monorepoDetector;
|
|
418
|
+
this.prTemplatePath = '/home/pedro-castanheira/Downloads/pull-request.template.md';
|
|
418
419
|
}
|
|
419
420
|
};
|
|
420
421
|
PrGeneratorService = _ts_decorate([
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/modules/git/services/pr-generator.service.ts"],"sourcesContent":["import { Injectable } from '@nestjs/common';\nimport { execSync } from 'child_process';\nimport { HumanMessage, SystemMessage } from '@langchain/core/messages';\nimport { MultiLlmService } from '../../../common/services/multi-llm.service';\nimport { MonorepoDetectorService } from './monorepo-detector.service';\n\nexport interface CommitInfo {\n hash: string;\n message: string;\n author: string;\n date: string;\n files: string[];\n diff: string;\n}\n\nexport interface PRDescription {\n title: string;\n description: string;\n commits: { hash: string; summary: string; details: string }[];\n}\n\nexport interface PRCreationResult {\n success: boolean;\n url?: string;\n error?: string;\n description?: string;\n platform: 'github' | 'azure' | 'gitlab' | 'bitbucket' | 'unknown';\n}\n\n@Injectable()\nexport class PrGeneratorService {\n constructor(\n private readonly multiLlmService: MultiLlmService,\n private readonly monorepoDetector: MonorepoDetectorService,\n ) {}\n\n getCurrentBranch(): string {\n try {\n return execSync('git branch --show-current', { \n cwd: process.cwd(), \n encoding: 'utf-8' \n }).trim();\n } catch {\n return 'unknown';\n }\n }\n\n detectDefaultBaseBranch(): string {\n try {\n const cwd = process.cwd();\n const candidates = ['main', 'master', 'develop'];\n \n for (const branch of candidates) {\n try {\n execSync(`git rev-parse --verify ${branch} 2>/dev/null || git rev-parse --verify origin/${branch} 2>/dev/null`, { \n cwd, \n stdio: 'ignore' \n });\n return branch;\n } catch {\n }\n }\n \n return 'main';\n } catch {\n return 'main';\n }\n }\n\n detectPlatform(): { platform: 'github' | 'azure' | 'gitlab' | 'bitbucket' | 'unknown'; url: string } {\n try {\n const remoteUrl = execSync('git remote get-url origin', { \n cwd: process.cwd(), \n encoding: 'utf-8' \n }).trim();\n\n if (remoteUrl.includes('github.com')) {\n return { platform: 'github', url: remoteUrl };\n }\n if (remoteUrl.includes('dev.azure.com') || remoteUrl.includes('visualstudio.com')) {\n return { platform: 'azure', url: remoteUrl };\n }\n if (remoteUrl.includes('gitlab.com') || remoteUrl.includes('gitlab')) {\n return { platform: 'gitlab', url: remoteUrl };\n }\n if (remoteUrl.includes('bitbucket.org')) {\n return { platform: 'bitbucket', url: remoteUrl };\n }\n\n return { platform: 'unknown', url: remoteUrl };\n } catch {\n return { platform: 'unknown', url: '' };\n }\n }\n\n getCommitsNotInBase(baseBranch: string = 'develop'): CommitInfo[] {\n try {\n const cwd = process.cwd();\n \n try {\n execSync(`git rev-parse --verify ${baseBranch}`, { cwd, stdio: 'ignore' });\n } catch {\n try {\n execSync(`git rev-parse --verify origin/${baseBranch}`, { cwd, stdio: 'ignore' });\n } catch {\n return [];\n }\n }\n\n const logOutput = execSync(\n `git log ${baseBranch}..HEAD --pretty=format:\"%H|%s|%an|%ad\" --date=short`,\n { cwd, encoding: 'utf-8' }\n );\n\n if (!logOutput.trim()) {\n return [];\n }\n\n const commits: CommitInfo[] = [];\n const lines = logOutput.trim().split('\\n');\n\n for (const line of lines) {\n const [hash, message, author, date] = line.split('|');\n if (!hash) continue;\n\n const filesOutput = execSync(\n `git diff-tree --no-commit-id --name-only -r ${hash}`,\n { cwd, encoding: 'utf-8' }\n );\n const files = filesOutput.trim().split('\\n').filter(f => f);\n\n const diffOutput = execSync(\n `git show ${hash} --stat`,\n { cwd, encoding: 'utf-8' }\n );\n\n commits.push({\n hash: hash.slice(0, 7),\n message,\n author,\n date,\n files,\n diff: diffOutput,\n });\n }\n\n return commits.reverse();\n } catch (error) {\n return [];\n }\n }\n\n async analyzeCommit(commit: CommitInfo): Promise<{ summary: string; details: string }> {\n const llm = this.multiLlmService.createModel('cheap');\n\n const prompt = this.buildCommitAnalysisPrompt(commit);\n\n const response = await llm.invoke([\n new SystemMessage(this.getCommitAnalysisSystemPrompt()),\n new HumanMessage(prompt),\n ]);\n\n const content = this.extractContent(response.content);\n return this.parseCommitAnalysis(content);\n }\n\n async generatePRDescription(\n branchName: string, \n commits: CommitInfo[],\n baseBranch: string = 'develop',\n ): Promise<PRDescription> {\n const llm = this.multiLlmService.createModel('cheap');\n const prompt = this.buildSinglePrompt(branchName, commits, baseBranch);\n\n const response = await llm.invoke([\n new SystemMessage(this.getSingleAgentSystemPrompt()),\n new HumanMessage(prompt),\n ]);\n\n const content = this.extractContent(response.content);\n const { title, description, commitSummaries } = this.parseSingleResponse(content, commits);\n\n return {\n title: title || this.generateDefaultTitle(branchName),\n description,\n commits: commitSummaries,\n };\n }\n\n async createPR(\n title: string, \n description: string, \n baseBranch: string = 'develop'\n ): Promise<PRCreationResult> {\n const { platform } = this.detectPlatform();\n const branch = this.getCurrentBranch();\n\n if (platform !== 'github') {\n return {\n success: false,\n error: `Automatic PR creation not supported for ${platform}. Description generated and copied to clipboard.`,\n description: this.formatPRForClipboard(title, description, baseBranch),\n platform,\n };\n }\n\n try {\n execSync('which gh', { cwd: process.cwd() });\n } catch {\n return {\n success: false,\n error: 'GitHub CLI (gh) not found. Install from https://cli.github.com/',\n description: this.formatPRForClipboard(title, description, baseBranch),\n platform,\n };\n }\n\n try {\n const cwd = process.cwd();\n\n const tempFile = `/tmp/pr-body-${Date.now()}.md`;\n require('fs').writeFileSync(tempFile, description);\n\n try {\n const result = execSync(\n `gh pr create --title \"${title.replace(/\"/g, '\\\\\"')}\" --body-file \"${tempFile}\" --base \"${baseBranch}\"`,\n { cwd, encoding: 'utf-8' }\n );\n \n const urlMatch = result.match(/https:\\/\\/github\\.com\\/[^\\s]+/);\n \n return { \n success: true, \n url: urlMatch ? urlMatch[0] : undefined,\n platform,\n };\n } finally {\n try {\n require('fs').unlinkSync(tempFile);\n } catch {}\n }\n } catch (error: any) {\n const message = error.message || 'Failed to create PR';\n if (message.includes('already exists')) {\n return { \n success: false, \n error: 'A PR already exists for this branch',\n description: this.formatPRForClipboard(title, description, baseBranch),\n platform,\n };\n }\n return { \n success: false, \n error: message,\n description: this.formatPRForClipboard(title, description, baseBranch),\n platform,\n };\n }\n }\n\n copyToClipboard(text: string): boolean {\n try {\n const platform = process.platform;\n \n if (platform === 'darwin') {\n execSync(`echo ${JSON.stringify(text)} | pbcopy`);\n return true;\n } else if (platform === 'linux') {\n try {\n execSync(`echo ${JSON.stringify(text)} | xclip -selection clipboard`);\n return true;\n } catch {\n try {\n execSync(`echo ${JSON.stringify(text)} | xsel --clipboard --input`);\n return true;\n } catch {\n return false;\n }\n }\n } else if (platform === 'win32') {\n execSync(`echo ${JSON.stringify(text)} | clip`);\n return true;\n }\n \n return false;\n } catch {\n return false;\n }\n }\n\n formatPRForClipboard(title: string, description: string, baseBranch: string): string {\n return `# ${title}\\n\\n${description}\\n\\n---\\n**Base Branch:** ${baseBranch}\\n**Generated by:** Cast Code`;\n }\n\n getPRCreateUrl(platform: string, baseBranch: string): string | null {\n try {\n const remoteUrl = execSync('git remote get-url origin', { \n cwd: process.cwd(), \n encoding: 'utf-8' \n }).trim();\n\n const branch = this.getCurrentBranch();\n\n let httpsUrl = remoteUrl\n .replace(/^git@github\\.com:/, 'https://github.com/')\n .replace(/^git@gitlab\\.com:/, 'https://gitlab.com/')\n .replace(/^git@bitbucket\\.org:/, 'https://bitbucket.org/')\n .replace(/\\.git$/, '');\n\n switch (platform) {\n case 'github':\n return `${httpsUrl}/compare/${baseBranch}...${branch}?expand=1`;\n case 'gitlab':\n return `${httpsUrl}/merge_requests/new?merge_request[source_branch]=${branch}&merge_request[target_branch]=${baseBranch}`;\n case 'bitbucket':\n return `${httpsUrl}/pull-requests/new?source=${branch}&dest=${baseBranch}`;\n case 'azure':\n return null;\n default:\n return null;\n }\n } catch {\n return null;\n }\n }\n\n private buildCommitAnalysisPrompt(commit: CommitInfo): string {\n const monorepoInfo = this.monorepoDetector.detectMonorepo(process.cwd());\n const scope = this.monorepoDetector.determineScope(commit.files, monorepoInfo);\n\n return `Analyze this commit:\\n\\n**Commit:** ${commit.hash}\\n**Message:** ${commit.message}\\n**Author:** ${commit.author}\\n**Date:** ${commit.date}\\n**Scope:** ${scope || 'general'}\\n\\n**Files Changed:**\\n${commit.files.join('\\n')}\\n\\n**Diff Stats:**\\n${commit.diff}\\n\\nProvide:\\n1. A one-line summary (max 100 chars)\\n2. Detailed explanation of changes, approach, and impact`;\n }\n\n private buildPRDescriptionPrompt(\n branchName: string, \n commits: { hash: string; message: string; summary: string; details: string }[],\n baseBranch: string,\n ): string {\n const commitsSummary = commits.map((c, i) => \n `${i + 1}. **${c.hash}** - ${c.summary}\\n ${c.details.slice(0, 200)}...`\n ).join('\\n\\n');\n\n return `Create a PR description for branch \"${branchName}\" to \"${baseBranch}\".\\n\\n**Commits:**\\n${commitsSummary}\\n\\nGenerate:\\n1. PR title (use branch name as inspiration)\\n2. Description with: Overview, Changes, Technical Details, Testing`;\n }\n\n private getCommitAnalysisSystemPrompt(): string {\n return `Analyze a git commit. Provide:\\n\\n1. **Summary**: One sentence (max 100 chars)\\n2. **Details**: Detailed paragraph about changes\\n\\nFormat:\\nSUMMARY: <summary>\\n\\nDETAILS: <details>`;\n }\n\n private getPRDescriptionSystemPrompt(): string {\n return `Create a Pull Request description.\\n\\n**Title:** Concise, descriptive\\n\\n**Description Structure:**\\n\\`\\`\\`markdown\\n## Overview\\nBrief explanation\\n\\n## Changes\\n- Change 1\\n- Change 2\\n\\n## Technical Details\\nImplementation details\\n\\n## Testing\\nHow to test\\n\\`\\`\\``;\n }\n\n private parseCommitAnalysis(content: string): { summary: string; details: string } {\n const summaryMatch = content.match(/SUMMARY:\\s*(.+?)(?=\\n\\n|DETAILS:|$)/is);\n const detailsMatch = content.match(/DETAILS:\\s*(.+?)$/is);\n\n return {\n summary: summaryMatch ? summaryMatch[1].trim() : 'No summary available',\n details: detailsMatch ? detailsMatch[1].trim() : content,\n };\n }\n\n private parsePRDescription(content: string): { title: string; description: string } {\n const titleMatch = content.match(/^#?\\s*Title:?\\s*(.+?)(?=\\n\\n|\\n##|$)/i);\n const lines = content.split('\\n');\n const title = titleMatch ? titleMatch[1].trim() : lines[0].replace(/^#+\\s*/, '').trim();\n const description = titleMatch \n ? content.slice(content.indexOf(titleMatch[0]) + titleMatch[0].length).trim()\n : lines.slice(1).join('\\n').trim();\n\n return { title, description };\n }\n\n private buildSinglePrompt(branchName: string, commits: CommitInfo[], baseBranch: string): string {\n const commitsInfo = commits.map((c, i) => \n `${i + 1}. **${c.hash}** - ${c.message}\\n Files: ${c.files.slice(0, 5).join(', ')}${c.files.length > 5 ? '...' : ''}\\n Stats: ${c.diff.split('\\n').slice(-3, -1).join(' ')}`\n ).join('\\n\\n');\n\n return `Branch: ${branchName}\\nBase: ${baseBranch}\\nCommits: ${commits.length}\\n\\n${commitsInfo}`;\n }\n\n private getSingleAgentSystemPrompt(): string {\n return `You are a senior developer creating a Pull Request description. Analyze ALL commits and generate a comprehensive PR description.\n\n**OUTPUT FORMAT:**\nTITLE: <PR title based on branch name and overall changes>\n\nOVERVIEW: <2-3 sentences explaining what this PR accomplishes>\n\nCHANGES:\n- <key change 1>\n- <key change 2>\n- ...\n\nTECHNICAL_DETAILS: <important implementation details, architecture decisions>\n\nCOMMITS:\n<hash>: <one-line summary of what this commit does>\n(repeat for each commit)\n\nTESTING: <how to test these changes>`;\n }\n\n private parseSingleResponse(content: string, commits: CommitInfo[]): { \n title: string; \n description: string; \n commitSummaries: { hash: string; summary: string; details: string }[] \n } {\n const titleMatch = content.match(/TITLE:\\s*(.+?)(?=\\n\\n|\\n[A-Z]|$)/i);\n const overviewMatch = content.match(/OVERVIEW:\\s*([\\s\\S]+?)(?=\\n\\nCHANGES:|CHANGES:)/i);\n const changesMatch = content.match(/CHANGES:\\s*([\\s\\S]+?)(?=\\n\\nTECHNICAL_DETAILS:|TECHNICAL_DETAILS:)/i);\n const technicalMatch = content.match(/TECHNICAL_DETAILS:\\s*([\\s\\S]+?)(?=\\n\\nCOMMITS:|COMMITS:)/i);\n const commitsMatch = content.match(/COMMITS:\\s*([\\s\\S]+?)(?=\\n\\nTESTING:|TESTING:|$)/i);\n const testingMatch = content.match(/TESTING:\\s*([\\s\\S]+)$/i);\n\n const title = titleMatch ? titleMatch[1].trim() : '';\n \n const parts: string[] = [];\n \n if (overviewMatch) {\n parts.push('## Overview\\n' + overviewMatch[1].trim());\n }\n \n if (changesMatch) {\n parts.push('## Changes\\n' + changesMatch[1].trim());\n }\n \n if (technicalMatch) {\n parts.push('## Technical Details\\n' + technicalMatch[1].trim());\n }\n \n if (testingMatch) {\n parts.push('## Testing\\n' + testingMatch[1].trim());\n }\n\n const description = parts.join('\\n\\n');\n\n const commitSummaries: { hash: string; summary: string; details: string }[] = [];\n \n if (commitsMatch) {\n const commitsText = commitsMatch[1].trim();\n const lines = commitsText.split('\\n');\n \n for (const line of lines) {\n const match = line.match(/^([a-f0-9]+):\\s*(.+)$/i);\n if (match) {\n commitSummaries.push({\n hash: match[1].slice(0, 7),\n summary: match[2].trim(),\n details: '',\n });\n }\n }\n }\n\n if (commitSummaries.length === 0) {\n for (const commit of commits) {\n commitSummaries.push({\n hash: commit.hash,\n summary: commit.message.slice(0, 60),\n details: '',\n });\n }\n }\n\n return { title, description, commitSummaries };\n }\n\n private generateDefaultTitle(branchName: string): string {\n return branchName\n .replace(/^(feature|fix|hotfix|release)\\//, '')\n .split(/[-_]/)\n .map(word => word.charAt(0).toUpperCase() + word.slice(1))\n .join(' ');\n }\n\n private extractContent(content: unknown): string {\n if (typeof content === 'string') return content;\n if (Array.isArray(content) && content.length > 0) {\n const first = content[0];\n if (typeof first === 'object' && first !== null && 'text' in first) {\n return String(first.text);\n }\n }\n return String(content);\n }\n}\n"],"names":["PrGeneratorService","getCurrentBranch","execSync","cwd","process","encoding","trim","detectDefaultBaseBranch","candidates","branch","stdio","detectPlatform","remoteUrl","includes","platform","url","getCommitsNotInBase","baseBranch","logOutput","commits","lines","split","line","hash","message","author","date","filesOutput","files","filter","f","diffOutput","push","slice","diff","reverse","error","analyzeCommit","commit","llm","multiLlmService","createModel","prompt","buildCommitAnalysisPrompt","response","invoke","SystemMessage","getCommitAnalysisSystemPrompt","HumanMessage","content","extractContent","parseCommitAnalysis","generatePRDescription","branchName","buildSinglePrompt","getSingleAgentSystemPrompt","title","description","commitSummaries","parseSingleResponse","generateDefaultTitle","createPR","success","formatPRForClipboard","tempFile","Date","now","require","writeFileSync","result","replace","urlMatch","match","undefined","unlinkSync","copyToClipboard","text","JSON","stringify","getPRCreateUrl","httpsUrl","monorepoInfo","monorepoDetector","detectMonorepo","scope","determineScope","join","buildPRDescriptionPrompt","commitsSummary","map","c","i","summary","details","getPRDescriptionSystemPrompt","summaryMatch","detailsMatch","parsePRDescription","titleMatch","indexOf","length","commitsInfo","overviewMatch","changesMatch","technicalMatch","commitsMatch","testingMatch","parts","commitsText","word","charAt","toUpperCase","Array","isArray","first","String"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../src/modules/git/services/pr-generator.service.ts"],"sourcesContent":["import { Injectable } from '@nestjs/common';\nimport { execSync } from 'child_process';\nimport { HumanMessage, SystemMessage } from '@langchain/core/messages';\nimport { MultiLlmService } from '../../../common/services/multi-llm.service';\nimport { MonorepoDetectorService } from './monorepo-detector.service';\n\nexport interface CommitInfo {\n hash: string;\n message: string;\n author: string;\n date: string;\n files: string[];\n diff: string;\n}\n\nexport interface PRDescription {\n title: string;\n description: string;\n commits: { hash: string; summary: string; details: string }[];\n}\n\nexport interface PRCreationResult {\n success: boolean;\n url?: string;\n error?: string;\n description?: string;\n platform: 'github' | 'azure' | 'gitlab' | 'bitbucket' | 'unknown';\n}\n\n@Injectable()\nexport class PrGeneratorService {\n private prTemplateCache?: string;\n private readonly prTemplatePath = '/home/pedro-castanheira/Downloads/pull-request.template.md';\n\n constructor(\n private readonly multiLlmService: MultiLlmService,\n private readonly monorepoDetector: MonorepoDetectorService,\n ) {}\n\n getCurrentBranch(): string {\n try {\n return execSync('git branch --show-current', { \n cwd: process.cwd(), \n encoding: 'utf-8' \n }).trim();\n } catch {\n return 'unknown';\n }\n }\n\n detectDefaultBaseBranch(): string {\n try {\n const cwd = process.cwd();\n const candidates = ['main', 'master', 'develop'];\n \n for (const branch of candidates) {\n try {\n execSync(`git rev-parse --verify ${branch} 2>/dev/null || git rev-parse --verify origin/${branch} 2>/dev/null`, { \n cwd, \n stdio: 'ignore' \n });\n return branch;\n } catch {\n }\n }\n \n return 'main';\n } catch {\n return 'main';\n }\n }\n\n detectPlatform(): { platform: 'github' | 'azure' | 'gitlab' | 'bitbucket' | 'unknown'; url: string } {\n try {\n const remoteUrl = execSync('git remote get-url origin', { \n cwd: process.cwd(), \n encoding: 'utf-8' \n }).trim();\n\n if (remoteUrl.includes('github.com')) {\n return { platform: 'github', url: remoteUrl };\n }\n if (remoteUrl.includes('dev.azure.com') || remoteUrl.includes('visualstudio.com')) {\n return { platform: 'azure', url: remoteUrl };\n }\n if (remoteUrl.includes('gitlab.com') || remoteUrl.includes('gitlab')) {\n return { platform: 'gitlab', url: remoteUrl };\n }\n if (remoteUrl.includes('bitbucket.org')) {\n return { platform: 'bitbucket', url: remoteUrl };\n }\n\n return { platform: 'unknown', url: remoteUrl };\n } catch {\n return { platform: 'unknown', url: '' };\n }\n }\n\n getCommitsNotInBase(baseBranch: string = 'develop'): CommitInfo[] {\n try {\n const cwd = process.cwd();\n \n try {\n execSync(`git rev-parse --verify ${baseBranch}`, { cwd, stdio: 'ignore' });\n } catch {\n try {\n execSync(`git rev-parse --verify origin/${baseBranch}`, { cwd, stdio: 'ignore' });\n } catch {\n return [];\n }\n }\n\n const logOutput = execSync(\n `git log ${baseBranch}..HEAD --pretty=format:\"%H|%s|%an|%ad\" --date=short`,\n { cwd, encoding: 'utf-8' }\n );\n\n if (!logOutput.trim()) {\n return [];\n }\n\n const commits: CommitInfo[] = [];\n const lines = logOutput.trim().split('\\n');\n\n for (const line of lines) {\n const [hash, message, author, date] = line.split('|');\n if (!hash) continue;\n\n const filesOutput = execSync(\n `git diff-tree --no-commit-id --name-only -r ${hash}`,\n { cwd, encoding: 'utf-8' }\n );\n const files = filesOutput.trim().split('\\n').filter(f => f);\n\n const diffOutput = execSync(\n `git show ${hash} --stat`,\n { cwd, encoding: 'utf-8' }\n );\n\n commits.push({\n hash: hash.slice(0, 7),\n message,\n author,\n date,\n files,\n diff: diffOutput,\n });\n }\n\n return commits.reverse();\n } catch (error) {\n return [];\n }\n }\n\n async analyzeCommit(commit: CommitInfo): Promise<{ summary: string; details: string }> {\n const llm = this.multiLlmService.createModel('cheap');\n\n const prompt = this.buildCommitAnalysisPrompt(commit);\n\n const response = await llm.invoke([\n new SystemMessage(this.getCommitAnalysisSystemPrompt()),\n new HumanMessage(prompt),\n ]);\n\n const content = this.extractContent(response.content);\n return this.parseCommitAnalysis(content);\n }\n\n async generatePRDescription(\n branchName: string, \n commits: CommitInfo[],\n baseBranch: string = 'develop',\n ): Promise<PRDescription> {\n const llm = this.multiLlmService.createModel('cheap');\n const prompt = this.buildSinglePrompt(branchName, commits, baseBranch);\n\n const response = await llm.invoke([\n new SystemMessage(this.getSingleAgentSystemPrompt()),\n new HumanMessage(prompt),\n ]);\n\n const content = this.extractContent(response.content);\n const { title, description, commitSummaries } = this.parseSingleResponse(content, commits);\n\n return {\n title: title || this.generateDefaultTitle(branchName),\n description: description && description.trim().length > 0 ? description : this.getPRTemplate(),\n commits: commitSummaries,\n };\n }\n\n async createPR(\n title: string, \n description: string, \n baseBranch: string = 'develop'\n ): Promise<PRCreationResult> {\n const { platform } = this.detectPlatform();\n const branch = this.getCurrentBranch();\n\n if (platform !== 'github') {\n return {\n success: false,\n error: `Automatic PR creation not supported for ${platform}. Description generated and copied to clipboard.`,\n description: this.formatPRForClipboard(title, description, baseBranch),\n platform,\n };\n }\n\n try {\n execSync('which gh', { cwd: process.cwd() });\n } catch {\n return {\n success: false,\n error: 'GitHub CLI (gh) not found. Install from https://cli.github.com/',\n description: this.formatPRForClipboard(title, description, baseBranch),\n platform,\n };\n }\n\n try {\n const cwd = process.cwd();\n\n const tempFile = `/tmp/pr-body-${Date.now()}.md`;\n require('fs').writeFileSync(tempFile, description);\n\n try {\n const result = execSync(\n `gh pr create --title \"${title.replace(/\"/g, '\\\\\"')}\" --body-file \"${tempFile}\" --base \"${baseBranch}\"`,\n { cwd, encoding: 'utf-8' }\n );\n \n const urlMatch = result.match(/https:\\/\\/github\\.com\\/[^\\s]+/);\n \n return { \n success: true, \n url: urlMatch ? urlMatch[0] : undefined,\n platform,\n };\n } finally {\n try {\n require('fs').unlinkSync(tempFile);\n } catch {}\n }\n } catch (error: any) {\n const message = error.message || 'Failed to create PR';\n if (message.includes('already exists')) {\n return { \n success: false, \n error: 'A PR already exists for this branch',\n description: this.formatPRForClipboard(title, description, baseBranch),\n platform,\n };\n }\n return { \n success: false, \n error: message,\n description: this.formatPRForClipboard(title, description, baseBranch),\n platform,\n };\n }\n }\n\n copyToClipboard(text: string): boolean {\n try {\n const platform = process.platform;\n \n if (platform === 'darwin') {\n execSync(`echo ${JSON.stringify(text)} | pbcopy`);\n return true;\n } else if (platform === 'linux') {\n try {\n execSync(`echo ${JSON.stringify(text)} | xclip -selection clipboard`);\n return true;\n } catch {\n try {\n execSync(`echo ${JSON.stringify(text)} | xsel --clipboard --input`);\n return true;\n } catch {\n return false;\n }\n }\n } else if (platform === 'win32') {\n execSync(`echo ${JSON.stringify(text)} | clip`);\n return true;\n }\n \n return false;\n } catch {\n return false;\n }\n }\n\n formatPRForClipboard(title: string, description: string, baseBranch: string): string {\n return description;\n }\n\n getPRCreateUrl(platform: string, baseBranch: string): string | null {\n try {\n const remoteUrl = execSync('git remote get-url origin', { \n cwd: process.cwd(), \n encoding: 'utf-8' \n }).trim();\n\n const branch = this.getCurrentBranch();\n\n let httpsUrl = remoteUrl\n .replace(/^git@github\\.com:/, 'https://github.com/')\n .replace(/^git@gitlab\\.com:/, 'https://gitlab.com/')\n .replace(/^git@bitbucket\\.org:/, 'https://bitbucket.org/')\n .replace(/\\.git$/, '');\n\n switch (platform) {\n case 'github':\n return `${httpsUrl}/compare/${baseBranch}...${branch}?expand=1`;\n case 'gitlab':\n return `${httpsUrl}/merge_requests/new?merge_request[source_branch]=${branch}&merge_request[target_branch]=${baseBranch}`;\n case 'bitbucket':\n return `${httpsUrl}/pull-requests/new?source=${branch}&dest=${baseBranch}`;\n case 'azure':\n return null;\n default:\n return null;\n }\n } catch {\n return null;\n }\n }\n\n private buildCommitAnalysisPrompt(commit: CommitInfo): string {\n const monorepoInfo = this.monorepoDetector.detectMonorepo(process.cwd());\n const scope = this.monorepoDetector.determineScope(commit.files, monorepoInfo);\n\n return `Analyze this commit:\\n\\n**Commit:** ${commit.hash}\\n**Message:** ${commit.message}\\n**Author:** ${commit.author}\\n**Date:** ${commit.date}\\n**Scope:** ${scope || 'general'}\\n\\n**Files Changed:**\\n${commit.files.join('\\n')}\\n\\n**Diff Stats:**\\n${commit.diff}\\n\\nProvide:\\n1. A one-line summary (max 100 chars)\\n2. Detailed explanation of changes, approach, and impact`;\n }\n\n private getCommitAnalysisSystemPrompt(): string {\n return `Analyze a git commit. Provide:\\n\\n1. **Summary**: One sentence (max 100 chars)\\n2. **Details**: Detailed paragraph about changes\\n\\nFormat:\\nSUMMARY: <summary>\\n\\nDETAILS: <details>`;\n }\n\n private parseCommitAnalysis(content: string): { summary: string; details: string } {\n const summaryMatch = content.match(/SUMMARY:\\s*(.+?)(?=\\n\\n|DETAILS:|$)/is);\n const detailsMatch = content.match(/DETAILS:\\s*(.+?)$/is);\n\n return {\n summary: summaryMatch ? summaryMatch[1].trim() : 'No summary available',\n details: detailsMatch ? detailsMatch[1].trim() : content,\n };\n }\n\n private parsePRDescription(content: string): { title: string; description: string } {\n const titleMatch = content.match(/^#?\\s*Title:?\\s*(.+?)(?=\\n\\n|\\n##|$)/i);\n const lines = content.split('\\n');\n const title = titleMatch ? titleMatch[1].trim() : lines[0].replace(/^#+\\s*/, '').trim();\n const description = titleMatch \n ? content.slice(content.indexOf(titleMatch[0]) + titleMatch[0].length).trim()\n : lines.slice(1).join('\\n').trim();\n\n return { title, description };\n }\n\n private buildSinglePrompt(branchName: string, commits: CommitInfo[], baseBranch: string): string {\n const commitsInfo = commits.map((c, i) => \n `${i + 1}. **${c.hash}** - ${c.message}\\n Files: ${c.files.slice(0, 5).join(', ')}${c.files.length > 5 ? '...' : ''}\\n Stats: ${c.diff.split('\\n').slice(-3, -1).join(' ')}`\n ).join('\\n\\n');\n\n return `Branch: ${branchName}\\nBase: ${baseBranch}\\nCommits: ${commits.length}\\n\\n${commitsInfo}`;\n }\n\n private getSingleAgentSystemPrompt(): string {\n const template = this.getPRTemplate();\n return `You are a senior developer creating a Pull Request description. Analyze ALL commits and fill in the PR template below.\n\nRules:\n- Output ONLY the filled template.\n- Keep headings, checklists, and ordering exactly as shown.\n- Fill ONLY these sections with content: \"O que essa PR faz?\", \"O que foi mexido?\", \"O que eu fiz?\".\n- Leave the other sections blank for the user to fill in.\n- Do not add any extra sections beyond the template.\n- Keep the final reminder line.\n\nPR TEMPLATE:\n${template}`;\n }\n\n private parseSingleResponse(content: string, commits: CommitInfo[]): { \n title: string; \n description: string; \n commitSummaries: { hash: string; summary: string; details: string }[] \n } {\n const title = '';\n let description = content.trim();\n const requiredHeading = '## 🚀 O que essa PR faz?';\n const hasRequiredHeading = description.includes(requiredHeading);\n\n if (!hasRequiredHeading) {\n description = this.getPRTemplate();\n } else if (!description.includes('Não se esqueça de revisar essa descrição')) {\n description = `${description.trim()}\\n\\nNão se esqueça de revisar essa descrição`;\n }\n\n const commitSummaries: { hash: string; summary: string; details: string }[] = [];\n for (const commit of commits) {\n commitSummaries.push({\n hash: commit.hash,\n summary: commit.message.slice(0, 60),\n details: '',\n });\n }\n\n return { title, description, commitSummaries };\n }\n\n private generateDefaultTitle(branchName: string): string {\n return branchName;\n }\n\n private extractContent(content: unknown): string {\n if (typeof content === 'string') return content;\n if (Array.isArray(content) && content.length > 0) {\n const first = content[0];\n if (typeof first === 'object' && first !== null && 'text' in first) {\n return String(first.text);\n }\n }\n return String(content);\n }\n\n private getPRTemplate(): string {\n if (this.prTemplateCache) {\n return this.prTemplateCache;\n }\n\n try {\n const fs = require('fs');\n const raw = fs.readFileSync(this.prTemplatePath, 'utf-8').trimEnd();\n this.prTemplateCache = this.normalizeTemplate(raw);\n return this.prTemplateCache;\n } catch {\n const fallback = this.buildDefaultTemplate();\n this.prTemplateCache = fallback;\n return this.prTemplateCache;\n }\n }\n\n private normalizeTemplate(raw: string): string {\n const trimmed = raw.trimEnd();\n if (trimmed.includes('Não se esqueça de revisar essa descrição')) {\n return trimmed;\n }\n return `${trimmed}\\n\\nNão se esqueça de revisar essa descrição`;\n }\n\n private buildDefaultTemplate(): string {\n return [\n '## 🚀 O que essa PR faz?',\n '',\n '## 🛠️ O que foi mexido?',\n '',\n '## 💡 O que eu fiz? (Resumo técnico)',\n '',\n '## 🧪 Como testar?',\n '',\n '## ✅ Checklist do Dev',\n '',\n '## 📸 Prints / GIFs (Se for UI)',\n '',\n '## 🔗 Link da Task',\n '',\n 'Não se esqueça de revisar essa descrição',\n ].join('\\n');\n }\n}\n"],"names":["PrGeneratorService","getCurrentBranch","execSync","cwd","process","encoding","trim","detectDefaultBaseBranch","candidates","branch","stdio","detectPlatform","remoteUrl","includes","platform","url","getCommitsNotInBase","baseBranch","logOutput","commits","lines","split","line","hash","message","author","date","filesOutput","files","filter","f","diffOutput","push","slice","diff","reverse","error","analyzeCommit","commit","llm","multiLlmService","createModel","prompt","buildCommitAnalysisPrompt","response","invoke","SystemMessage","getCommitAnalysisSystemPrompt","HumanMessage","content","extractContent","parseCommitAnalysis","generatePRDescription","branchName","buildSinglePrompt","getSingleAgentSystemPrompt","title","description","commitSummaries","parseSingleResponse","generateDefaultTitle","length","getPRTemplate","createPR","success","formatPRForClipboard","tempFile","Date","now","require","writeFileSync","result","replace","urlMatch","match","undefined","unlinkSync","copyToClipboard","text","JSON","stringify","getPRCreateUrl","httpsUrl","monorepoInfo","monorepoDetector","detectMonorepo","scope","determineScope","join","summaryMatch","detailsMatch","summary","details","parsePRDescription","titleMatch","indexOf","commitsInfo","map","c","i","template","requiredHeading","hasRequiredHeading","Array","isArray","first","String","prTemplateCache","fs","raw","readFileSync","prTemplatePath","trimEnd","normalizeTemplate","fallback","buildDefaultTemplate","trimmed"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: architect
|
|
3
|
-
description: Software architect for designing systems and making architectural decisions
|
|
4
|
-
model: gpt-5.1-codex-mini
|
|
5
|
-
temperature: 0.2
|
|
6
|
-
skills:
|
|
7
|
-
- general/file-operations
|
|
8
|
-
- general/search
|
|
9
|
-
- specialized/api-design
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
# Architect Agent
|
|
13
|
-
|
|
14
|
-
You are a software architect specializing in system design and technical decisions.
|
|
15
|
-
|
|
16
|
-
## Responsibilities
|
|
17
|
-
- Design system architectures
|
|
18
|
-
- Make technology choices
|
|
19
|
-
- Define patterns and conventions
|
|
20
|
-
- Create technical specifications
|
|
21
|
-
- Review architectural decisions
|
|
22
|
-
|
|
23
|
-
## Guidelines
|
|
24
|
-
- Consider scalability and maintainability
|
|
25
|
-
- Document trade-offs for decisions
|
|
26
|
-
- Follow SOLID principles
|
|
27
|
-
- Prefer simple solutions over complex ones
|
|
28
|
-
- Consider the team's expertise
|
|
29
|
-
|
|
30
|
-
## Analysis Approach
|
|
31
|
-
1. Understand current architecture
|
|
32
|
-
2. Identify requirements and constraints
|
|
33
|
-
3. Evaluate multiple approaches
|
|
34
|
-
4. Recommend with justification
|
|
35
|
-
5. Define implementation path
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: backend
|
|
3
|
-
description: Backend specialist for API and server-side development
|
|
4
|
-
model: gpt-5.1-codex-mini
|
|
5
|
-
temperature: 0.1
|
|
6
|
-
skills:
|
|
7
|
-
- general/file-operations
|
|
8
|
-
- general/search
|
|
9
|
-
- specialized/api-design
|
|
10
|
-
- specialized/database-operations
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
# Backend Agent
|
|
14
|
-
|
|
15
|
-
You are a backend developer specializing in APIs and server-side systems.
|
|
16
|
-
|
|
17
|
-
## Responsibilities
|
|
18
|
-
- Design and implement APIs
|
|
19
|
-
- Handle data modeling
|
|
20
|
-
- Manage database operations
|
|
21
|
-
- Implement authentication/authorization
|
|
22
|
-
- Optimize queries and performance
|
|
23
|
-
|
|
24
|
-
## Guidelines
|
|
25
|
-
- Follow REST or GraphQL conventions
|
|
26
|
-
- Validate all inputs
|
|
27
|
-
- Handle errors gracefully
|
|
28
|
-
- Log appropriately
|
|
29
|
-
- Consider rate limiting
|
|
30
|
-
- Implement proper auth checks
|
|
31
|
-
|
|
32
|
-
## Security Focus
|
|
33
|
-
- Sanitize inputs
|
|
34
|
-
- Use parameterized queries
|
|
35
|
-
- Implement proper CORS
|
|
36
|
-
- Validate JWT tokens
|
|
37
|
-
- Hash passwords correctly
|
|
38
|
-
|
|
39
|
-
## Database Best Practices
|
|
40
|
-
- Use migrations
|
|
41
|
-
- Index appropriately
|
|
42
|
-
- Avoid N+1 queries
|
|
43
|
-
- Use transactions when needed
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: coder
|
|
3
|
-
description: General purpose coding agent for implementing features and fixing bugs
|
|
4
|
-
model: gpt-5.1-codex-mini
|
|
5
|
-
temperature: 0.1
|
|
6
|
-
skills:
|
|
7
|
-
- general/file-operations
|
|
8
|
-
- general/search
|
|
9
|
-
- general/git-operations
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
# Coder Agent
|
|
13
|
-
|
|
14
|
-
You are a skilled software developer focused on writing clean, maintainable code.
|
|
15
|
-
|
|
16
|
-
## Responsibilities
|
|
17
|
-
- Implement new features following existing patterns
|
|
18
|
-
- Fix bugs with minimal changes
|
|
19
|
-
- Write idiomatic code for the project's language
|
|
20
|
-
- Follow the project's coding conventions
|
|
21
|
-
|
|
22
|
-
## Guidelines
|
|
23
|
-
- Always read existing code before making changes
|
|
24
|
-
- Preserve indentation and formatting
|
|
25
|
-
- Make minimal, focused changes
|
|
26
|
-
- Do not add unnecessary comments
|
|
27
|
-
- Test your changes when possible
|
|
28
|
-
|
|
29
|
-
## Process
|
|
30
|
-
1. Understand the requirement
|
|
31
|
-
2. Read relevant existing code
|
|
32
|
-
3. Plan the implementation
|
|
33
|
-
4. Write the code
|
|
34
|
-
5. Verify the changes work
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: devops
|
|
3
|
-
description: DevOps specialist for infrastructure and deployment
|
|
4
|
-
model: gpt-5.1-codex-mini
|
|
5
|
-
temperature: 0.1
|
|
6
|
-
skills:
|
|
7
|
-
- general/file-operations
|
|
8
|
-
- general/search
|
|
9
|
-
- general/git-operations
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
# DevOps Agent
|
|
13
|
-
|
|
14
|
-
You are a DevOps engineer specializing in infrastructure and CI/CD.
|
|
15
|
-
|
|
16
|
-
## Responsibilities
|
|
17
|
-
- Configure CI/CD pipelines
|
|
18
|
-
- Manage infrastructure as code
|
|
19
|
-
- Handle containerization
|
|
20
|
-
- Set up monitoring
|
|
21
|
-
- Manage deployments
|
|
22
|
-
|
|
23
|
-
## Technologies
|
|
24
|
-
- Docker/Kubernetes
|
|
25
|
-
- GitHub Actions/GitLab CI
|
|
26
|
-
- Terraform/Pulumi
|
|
27
|
-
- Cloud platforms (AWS/GCP/Azure)
|
|
28
|
-
|
|
29
|
-
## Guidelines
|
|
30
|
-
- Infrastructure as code always
|
|
31
|
-
- Automate everything possible
|
|
32
|
-
- Implement proper secrets management
|
|
33
|
-
- Use multi-stage builds
|
|
34
|
-
- Set up proper logging/monitoring
|
|
35
|
-
- Follow least privilege principle
|
|
36
|
-
|
|
37
|
-
## Deployment Best Practices
|
|
38
|
-
- Use rolling deployments
|
|
39
|
-
- Implement health checks
|
|
40
|
-
- Set up rollback procedures
|
|
41
|
-
- Monitor post-deployment
|
|
42
|
-
- Document runbooks
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: frontend
|
|
3
|
-
description: Frontend specialist for UI/UX implementation
|
|
4
|
-
model: gpt-5.1-codex-mini
|
|
5
|
-
temperature: 0.1
|
|
6
|
-
skills:
|
|
7
|
-
- general/file-operations
|
|
8
|
-
- general/search
|
|
9
|
-
- specialized/react-patterns
|
|
10
|
-
- specialized/frontend-bootstrap
|
|
11
|
-
mcp:
|
|
12
|
-
- figma
|
|
13
|
-
---
|
|
14
|
-
|
|
15
|
-
# Frontend Agent
|
|
16
|
-
|
|
17
|
-
You are a frontend developer specializing in modern web interfaces.
|
|
18
|
-
|
|
19
|
-
## Responsibilities
|
|
20
|
-
- Turn Figma prototypes into production-ready frontend structures
|
|
21
|
-
- Implement UI components
|
|
22
|
-
- Ensure accessibility (WCAG)
|
|
23
|
-
- Optimize performance
|
|
24
|
-
- Handle responsive design
|
|
25
|
-
- Manage client-side state
|
|
26
|
-
|
|
27
|
-
## Technologies
|
|
28
|
-
- React/Vue/Svelte (per project)
|
|
29
|
-
- TypeScript
|
|
30
|
-
- CSS-in-JS or Tailwind
|
|
31
|
-
- State management libraries
|
|
32
|
-
|
|
33
|
-
## Guidelines
|
|
34
|
-
- Use semantic HTML
|
|
35
|
-
- Follow component composition patterns
|
|
36
|
-
- Implement proper error boundaries
|
|
37
|
-
- Lazy load when appropriate
|
|
38
|
-
- Use proper ARIA attributes
|
|
39
|
-
|
|
40
|
-
## When Using Figma MCP
|
|
41
|
-
- Extract primary screens and user flows first
|
|
42
|
-
- Identify core UI primitives (button, input, table, modal, card, nav, layout)
|
|
43
|
-
- Extract design tokens (colors, typography, spacing, radius, shadows)
|
|
44
|
-
- Generate project scaffold, routes, and component library before page wiring
|
|
45
|
-
- Match spacing and typography with responsive behavior
|
|
46
|
-
- Keep reusable components isolated from page-level composition
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: reviewer
|
|
3
|
-
description: Code reviewer for quality assurance and best practices
|
|
4
|
-
model: gpt-5.1-codex-mini
|
|
5
|
-
temperature: 0.1
|
|
6
|
-
skills:
|
|
7
|
-
- general/file-operations
|
|
8
|
-
- general/search
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
# Reviewer Agent
|
|
12
|
-
|
|
13
|
-
You are an experienced code reviewer focused on code quality and best practices.
|
|
14
|
-
|
|
15
|
-
## Responsibilities
|
|
16
|
-
- Review code for bugs and issues
|
|
17
|
-
- Check for security vulnerabilities
|
|
18
|
-
- Verify coding standards compliance
|
|
19
|
-
- Suggest improvements
|
|
20
|
-
- Ensure test coverage
|
|
21
|
-
|
|
22
|
-
## Review Checklist
|
|
23
|
-
- Logic correctness
|
|
24
|
-
- Error handling
|
|
25
|
-
- Security (injection, XSS, auth)
|
|
26
|
-
- Performance implications
|
|
27
|
-
- Code readability
|
|
28
|
-
- Test coverage
|
|
29
|
-
|
|
30
|
-
## Feedback Style
|
|
31
|
-
- Be specific and actionable
|
|
32
|
-
- Explain the "why" behind suggestions
|
|
33
|
-
- Prioritize critical issues
|
|
34
|
-
- Acknowledge good patterns
|
|
35
|
-
- Provide examples when helpful
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: tester
|
|
3
|
-
description: Testing specialist for quality assurance and test automation
|
|
4
|
-
model: gpt-5.1-codex-mini
|
|
5
|
-
temperature: 0.1
|
|
6
|
-
skills:
|
|
7
|
-
- general/file-operations
|
|
8
|
-
- general/search
|
|
9
|
-
- specialized/testing-strategies
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
# Tester Agent
|
|
13
|
-
|
|
14
|
-
You are a QA engineer specializing in test automation and quality assurance.
|
|
15
|
-
|
|
16
|
-
## Responsibilities
|
|
17
|
-
- Write unit tests
|
|
18
|
-
- Create integration tests
|
|
19
|
-
- Design E2E test scenarios
|
|
20
|
-
- Identify edge cases
|
|
21
|
-
- Ensure test coverage
|
|
22
|
-
|
|
23
|
-
## Testing Strategy
|
|
24
|
-
- Unit tests for business logic
|
|
25
|
-
- Integration tests for APIs
|
|
26
|
-
- E2E tests for critical flows
|
|
27
|
-
- Performance tests for bottlenecks
|
|
28
|
-
|
|
29
|
-
## Guidelines
|
|
30
|
-
- Follow AAA pattern (Arrange, Act, Assert)
|
|
31
|
-
- Test behavior, not implementation
|
|
32
|
-
- Use meaningful test names
|
|
33
|
-
- Mock external dependencies
|
|
34
|
-
- Keep tests independent
|
|
35
|
-
- Aim for deterministic tests
|
|
36
|
-
|
|
37
|
-
## Coverage Goals
|
|
38
|
-
- Critical paths: 100%
|
|
39
|
-
- Business logic: 80%+
|
|
40
|
-
- Edge cases: comprehensive
|
|
41
|
-
- Error handling: thorough
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: file-operations
|
|
3
|
-
description: Read, write, and edit files in the filesystem
|
|
4
|
-
tools:
|
|
5
|
-
- read_file
|
|
6
|
-
- write_file
|
|
7
|
-
- edit_file
|
|
8
|
-
- glob
|
|
9
|
-
- ls
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
# File Operations — Domain Knowledge
|
|
13
|
-
|
|
14
|
-
This skill teaches you how to work with files effectively. Study this to learn patterns, avoid mistakes, and make better decisions.
|
|
15
|
-
|
|
16
|
-
## Core Principle: Read → Understand → Edit → Verify
|
|
17
|
-
|
|
18
|
-
Every file operation follows this cycle. NEVER skip steps.
|
|
19
|
-
|
|
20
|
-
## Tool Mastery
|
|
21
|
-
|
|
22
|
-
### read_file
|
|
23
|
-
- **When**: Before ANY edit, to answer questions, to verify changes
|
|
24
|
-
- **Pattern**: Read the whole file first, then specific sections with offset/limit for large files
|
|
25
|
-
- **Anti-pattern**: Reading 5 lines of a 500-line file and guessing the rest
|
|
26
|
-
|
|
27
|
-
### write_file
|
|
28
|
-
- **When**: Creating NEW files only. Never for existing files.
|
|
29
|
-
- **Anti-pattern**: Using write_file on existing files (overwrites everything — use edit_file)
|
|
30
|
-
|
|
31
|
-
### edit_file
|
|
32
|
-
- **When**: Modifying existing files with precise string replacement
|
|
33
|
-
- **Critical**: The `old_string` must be UNIQUE in the file. Include 2-3 surrounding lines for uniqueness.
|
|
34
|
-
- **Anti-pattern**: Providing just `const x = 1` when there are 5 similar lines
|
|
35
|
-
- **Tip**: Use `replace_all=true` ONLY when renaming across the entire file
|
|
36
|
-
|
|
37
|
-
### glob
|
|
38
|
-
- **When**: Finding files by name pattern. Always the FIRST step in discovery.
|
|
39
|
-
- **Key patterns**: `**/*.ts`, `src/**/*.service.ts`, `*.{js,ts,jsx,tsx}`
|
|
40
|
-
|
|
41
|
-
### ls
|
|
42
|
-
- **When**: Quick directory overview, understanding project structure
|
|
43
|
-
|
|
44
|
-
## Decision Framework
|
|
45
|
-
|
|
46
|
-
| Situation | Tool | Why |
|
|
47
|
-
|-----------|------|-----|
|
|
48
|
-
| What's in this file? | read_file | Direct content access |
|
|
49
|
-
| Find all test files | glob `**/*.test.ts` | Pattern matching |
|
|
50
|
-
| Fix this line | read_file → edit_file | Must read first |
|
|
51
|
-
| Create a new util | write_file | New file creation |
|
|
52
|
-
| Find where X is defined | glob → grep → read_file | Progressive narrowing |
|
|
53
|
-
|
|
54
|
-
## Common Mistakes
|
|
55
|
-
|
|
56
|
-
1. **Editing without reading** — You WILL get the old_string wrong
|
|
57
|
-
2. **Assuming file structure** — Always verify with ls or glob first
|
|
58
|
-
3. **Overwriting with write_file** — Use edit_file for existing files
|
|
59
|
-
4. **Non-unique old_string** — Add more context lines to make it unique
|
|
60
|
-
5. **Not verifying after edit** — Always re-read to confirm changes
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: git-operations
|
|
3
|
-
description: Git version control operations
|
|
4
|
-
tools:
|
|
5
|
-
- shell
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Git Operations — Domain Knowledge
|
|
9
|
-
|
|
10
|
-
This skill teaches you how to work with Git safely and effectively. Study this to learn safe workflows, commit conventions, and recovery techniques.
|
|
11
|
-
|
|
12
|
-
## Core Principle: Check → Stage → Commit → Verify
|
|
13
|
-
|
|
14
|
-
Always know the state before changing it.
|
|
15
|
-
|
|
16
|
-
## Safe Workflow
|
|
17
|
-
|
|
18
|
-
```
|
|
19
|
-
1. git status # What's the current state?
|
|
20
|
-
2. git diff # What exactly changed?
|
|
21
|
-
3. git add <specific files> # Stage only what's needed
|
|
22
|
-
4. git diff --staged # Verify what's being committed
|
|
23
|
-
5. git commit -m "clear message" # Commit with intent
|
|
24
|
-
6. git status # Verify clean state
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
## Commit Message Convention
|
|
28
|
-
|
|
29
|
-
Types: feat, fix, refactor, docs, test, chore, style, perf
|
|
30
|
-
Rule: First line < 50 chars, imperative mood ("Add feature" not "Added feature")
|
|
31
|
-
|
|
32
|
-
## DANGER ZONE — Commands That Need User Confirmation
|
|
33
|
-
|
|
34
|
-
| Command | Risk |
|
|
35
|
-
|---------|------|
|
|
36
|
-
| `git push --force` | Overwrites remote history |
|
|
37
|
-
| `git reset --hard` | Destroys local changes |
|
|
38
|
-
| `git clean -f` | Deletes untracked files |
|
|
39
|
-
| `git branch -D` | Force-deletes a branch |
|
|
40
|
-
| `git checkout .` | Discards all unstaged changes |
|
|
41
|
-
|
|
42
|
-
## Safe Commands (No Confirmation Needed)
|
|
43
|
-
|
|
44
|
-
- `git status`, `git log`, `git diff`, `git branch`
|
|
45
|
-
- `git add <specific_file>` (not `git add -A`)
|
|
46
|
-
- `git commit -m "message"` (with proper message)
|
|
47
|
-
- `git stash` / `git stash pop`
|
|
48
|
-
- `git fetch`
|
|
49
|
-
|
|
50
|
-
## Recovery Techniques
|
|
51
|
-
|
|
52
|
-
| Problem | Solution |
|
|
53
|
-
|---------|----------|
|
|
54
|
-
| Wrong commit message | `git commit --amend` (if not pushed) |
|
|
55
|
-
| Committed wrong file | `git reset HEAD~1` (soft) → re-stage |
|
|
56
|
-
| Need to undo last commit | `git reset --soft HEAD~1` |
|
|
57
|
-
| Accidentally deleted file | `git checkout -- <file>` |
|
|
58
|
-
| Find when bug introduced | `git bisect start` |
|
|
59
|
-
| See who changed a line | `git blame <file>` |
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: planning
|
|
3
|
-
description: Task planning and decomposition
|
|
4
|
-
tools:
|
|
5
|
-
- read_file
|
|
6
|
-
- glob
|
|
7
|
-
- enter_plan_mode
|
|
8
|
-
- exit_plan_mode
|
|
9
|
-
- task_create
|
|
10
|
-
- task_update
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
# Planning — Domain Knowledge
|
|
14
|
-
|
|
15
|
-
This skill teaches you how to plan complex work before executing it. Study this to learn when to plan, how to decompose tasks, and how to create actionable plans.
|
|
16
|
-
|
|
17
|
-
## Core Principle: Think Before You Act
|
|
18
|
-
|
|
19
|
-
The time you spend planning saves 5x the time you'd waste fixing mistakes.
|
|
20
|
-
|
|
21
|
-
## When to Plan (Decision Framework)
|
|
22
|
-
|
|
23
|
-
| Situation | Plan needed? | Why |
|
|
24
|
-
|-----------|-------------|-----|
|
|
25
|
-
| Fix a typo | No | Single, obvious change |
|
|
26
|
-
| Add a function to existing file | No | Clear scope |
|
|
27
|
-
| Add a new feature (3+ files) | **YES** | Multiple touchpoints |
|
|
28
|
-
| Refactor a module | **YES** | Ripple effects |
|
|
29
|
-
| Change an API contract | **YES** | Breaking changes possible |
|
|
30
|
-
| Debug a complex bug | Maybe | Investigate first, plan the fix |
|
|
31
|
-
| User says "implement X" where X is vague | **YES** | Need to clarify scope |
|
|
32
|
-
|
|
33
|
-
## Planning Process
|
|
34
|
-
|
|
35
|
-
### Phase 1: Discovery (BEFORE plan_mode)
|
|
36
|
-
1. `glob` to understand project structure
|
|
37
|
-
2. `read_file` key files (entry points, configs, relevant modules)
|
|
38
|
-
3. `grep` to find related code and patterns
|
|
39
|
-
4. Identify ALL files that will be touched
|
|
40
|
-
|
|
41
|
-
### Phase 2: Plan (IN plan_mode)
|
|
42
|
-
1. `enter_plan_mode` — signals you're planning, not executing
|
|
43
|
-
2. List every file to create/modify with specific changes
|
|
44
|
-
3. Order by dependency (don't modify callers before callees)
|
|
45
|
-
4. Identify risks and edge cases
|
|
46
|
-
5. Define verification steps
|
|
47
|
-
6. `exit_plan_mode` — present plan for user approval
|
|
48
|
-
|
|
49
|
-
### Phase 3: Execute (AFTER approval)
|
|
50
|
-
1. Create tasks with `task_create` for each step
|
|
51
|
-
2. Execute sequentially, marking tasks complete
|
|
52
|
-
3. Verify after each step
|
|
53
|
-
4. Run tests at the end
|
|
54
|
-
|
|
55
|
-
## Plan Template
|
|
56
|
-
|
|
57
|
-
```markdown
|
|
58
|
-
## Goal
|
|
59
|
-
[What we're achieving]
|
|
60
|
-
|
|
61
|
-
## Changes
|
|
62
|
-
1. **file1.ts** — [what changes and why]
|
|
63
|
-
2. **file2.ts** — [what changes and why]
|
|
64
|
-
|
|
65
|
-
## Order of Operations
|
|
66
|
-
1. First: [foundation changes]
|
|
67
|
-
2. Then: [dependent changes]
|
|
68
|
-
3. Finally: [verification]
|
|
69
|
-
|
|
70
|
-
## Risks
|
|
71
|
-
- [What could go wrong and mitigation]
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
## Task Decomposition Rules
|
|
75
|
-
|
|
76
|
-
### Good tasks are:
|
|
77
|
-
- **Specific**: "Add validateEmail function to utils/validation.ts"
|
|
78
|
-
- **Independent**: Can be verified in isolation when possible
|
|
79
|
-
- **Small**: 1-2 file changes per task
|
|
80
|
-
- **Ordered**: Dependencies are explicit
|
|
81
|
-
|
|
82
|
-
### Anti-patterns:
|
|
83
|
-
- "Implement everything" (too vague)
|
|
84
|
-
- "Fix the code" (what code? what fix?)
|
|
85
|
-
- Tasks that can't be verified
|
|
86
|
-
- Skipping the planning step for complex work
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: search
|
|
3
|
-
description: Search for patterns and content in the codebase
|
|
4
|
-
tools:
|
|
5
|
-
- grep
|
|
6
|
-
- glob
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
# Search — Domain Knowledge
|
|
10
|
-
|
|
11
|
-
This skill teaches you how to find anything in a codebase efficiently. Study this to learn search strategies and progressive narrowing techniques.
|
|
12
|
-
|
|
13
|
-
## Core Principle: Broad → Narrow → Precise
|
|
14
|
-
|
|
15
|
-
Never start with a narrow search. Cast a wide net first, then refine.
|
|
16
|
-
|
|
17
|
-
## Search Strategy Matrix
|
|
18
|
-
|
|
19
|
-
| I need to find... | First try | Fallback |
|
|
20
|
-
|-------------------|-----------|----------|
|
|
21
|
-
| A file by name | `glob **/*filename*` | `glob **/*.ext` |
|
|
22
|
-
| A function definition | `grep "function name\|const name"` | Per-file type search |
|
|
23
|
-
| Where X is used | `grep "X"` files_with_matches | `grep "import.*X"` |
|
|
24
|
-
| A config value | `glob **/*.{json,yaml,toml,env}` | `grep "KEY_NAME"` |
|
|
25
|
-
| Dead code | `grep "export.*FuncName"` then `grep "FuncName"` (compare counts) | |
|
|
26
|
-
|
|
27
|
-
## Regex Patterns Every Developer Needs
|
|
28
|
-
|
|
29
|
-
### Finding Definitions
|
|
30
|
-
- `class\s+ClassName` — Class definition
|
|
31
|
-
- `function\s+funcName` — Function declaration
|
|
32
|
-
- `const\s+funcName\s*=` — Arrow function
|
|
33
|
-
- `interface\s+InterfaceName` — TypeScript interface
|
|
34
|
-
- `export\s+(default\s+)?` — Exports
|
|
35
|
-
|
|
36
|
-
### Finding Usage
|
|
37
|
-
- `import.*{.*Name.*}.*from` — Named imports
|
|
38
|
-
- `new\s+ClassName` — Instantiation
|
|
39
|
-
- `Name\(` — Function calls
|
|
40
|
-
|
|
41
|
-
### Finding Problems
|
|
42
|
-
- `TODO|FIXME|HACK|XXX` — Developer notes
|
|
43
|
-
- `console\.(log|error|warn)` — Debug output
|
|
44
|
-
- `\.catch\(\s*\)` — Empty catch blocks
|
|
45
|
-
|
|
46
|
-
## Progressive Narrowing Technique
|
|
47
|
-
|
|
48
|
-
1. **Discover**: `glob "**/*.ts"` → understand the file landscape
|
|
49
|
-
2. **Locate**: `grep "pattern"` with `output_mode=files_with_matches` → find candidate files
|
|
50
|
-
3. **Context**: `grep "pattern"` with `context_lines=5` on specific files → see surrounding code
|
|
51
|
-
4. **Read**: `read_file` the most promising candidates → full understanding
|
|
52
|
-
|
|
53
|
-
## Common Mistakes
|
|
54
|
-
|
|
55
|
-
1. **Too specific too early** — Search for parts of the string, not the exact thing
|
|
56
|
-
2. **Wrong file types** — Search `.ts` AND `.tsx` and `.js`
|
|
57
|
-
3. **Case sensitivity** — Always consider case-insensitive first
|
|
58
|
-
4. **Giving up after one miss** — Try synonyms, partial matches, different patterns
|
|
59
|
-
5. **Not using context_lines** — A match without context is often useless
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: api-design
|
|
3
|
-
description: REST and GraphQL API design patterns
|
|
4
|
-
tools:
|
|
5
|
-
- read_file
|
|
6
|
-
- write_file
|
|
7
|
-
- edit_file
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
# API Design — Domain Knowledge
|
|
11
|
-
|
|
12
|
-
This skill teaches you how to design clean, consistent APIs. Study this to learn REST conventions, error handling patterns, and API best practices.
|
|
13
|
-
|
|
14
|
-
## REST Conventions
|
|
15
|
-
|
|
16
|
-
### HTTP Methods
|
|
17
|
-
| Method | Purpose | Idempotent | Body |
|
|
18
|
-
|--------|---------|------------|------|
|
|
19
|
-
| GET | Read | Yes | No |
|
|
20
|
-
| POST | Create | No | Yes |
|
|
21
|
-
| PUT | Replace | Yes | Yes |
|
|
22
|
-
| PATCH | Partial update | Yes | Yes |
|
|
23
|
-
| DELETE | Remove | Yes | No |
|
|
24
|
-
|
|
25
|
-
### URL Structure
|
|
26
|
-
- `/users` — Collection (GET all, POST create)
|
|
27
|
-
- `/users/:id` — Single resource (GET, PUT, PATCH, DELETE)
|
|
28
|
-
- `/users/:id/posts` — Nested resource
|
|
29
|
-
- Never: `/getUser`, `/createUser` (verbs in URLs)
|
|
30
|
-
|
|
31
|
-
### Status Codes (Know These)
|
|
32
|
-
| Code | Meaning | When |
|
|
33
|
-
|------|---------|------|
|
|
34
|
-
| 200 | OK | Successful GET, PUT, PATCH |
|
|
35
|
-
| 201 | Created | Successful POST |
|
|
36
|
-
| 204 | No Content | Successful DELETE |
|
|
37
|
-
| 400 | Bad Request | Validation failure |
|
|
38
|
-
| 401 | Unauthorized | Missing/invalid auth |
|
|
39
|
-
| 403 | Forbidden | Valid auth, no permission |
|
|
40
|
-
| 404 | Not Found | Resource doesn't exist |
|
|
41
|
-
| 409 | Conflict | Duplicate, version mismatch |
|
|
42
|
-
| 422 | Unprocessable | Valid syntax, invalid semantics |
|
|
43
|
-
| 500 | Server Error | Unexpected failure |
|
|
44
|
-
|
|
45
|
-
## Response Envelope Pattern
|
|
46
|
-
|
|
47
|
-
```json
|
|
48
|
-
{
|
|
49
|
-
"data": { ... },
|
|
50
|
-
"meta": { "page": 1, "totalPages": 10, "total": 100 },
|
|
51
|
-
"errors": []
|
|
52
|
-
}
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
## Error Response Pattern
|
|
56
|
-
|
|
57
|
-
```json
|
|
58
|
-
{
|
|
59
|
-
"error": {
|
|
60
|
-
"code": "VALIDATION_FAILED",
|
|
61
|
-
"message": "Human-readable description",
|
|
62
|
-
"details": [
|
|
63
|
-
{ "field": "email", "message": "Invalid format" }
|
|
64
|
-
]
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
## API Design Checklist
|
|
70
|
-
|
|
71
|
-
1. **Consistent naming** — plural nouns, kebab-case
|
|
72
|
-
2. **Pagination** — offset/limit or cursor-based for lists
|
|
73
|
-
3. **Filtering** — query params: `?status=active&sort=-created`
|
|
74
|
-
4. **Versioning** — URL path `/api/v1/` (simplest)
|
|
75
|
-
5. **Auth** — Bearer token in Authorization header
|
|
76
|
-
6. **Rate limiting** — Return 429 with Retry-After header
|
|
77
|
-
7. **CORS** — Configure allowed origins explicitly
|
|
78
|
-
|
|
79
|
-
## Common Mistakes
|
|
80
|
-
|
|
81
|
-
1. **Verbs in URLs** — Use HTTP methods instead
|
|
82
|
-
2. **Inconsistent response format** — Always same envelope
|
|
83
|
-
3. **200 for errors** — Use proper status codes
|
|
84
|
-
4. **No pagination** — Always paginate collections
|
|
85
|
-
5. **Leaking internals** — Don't expose DB IDs or stack traces
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: database-operations
|
|
3
|
-
description: Database design and query optimization
|
|
4
|
-
tools:
|
|
5
|
-
- read_file
|
|
6
|
-
- write_file
|
|
7
|
-
- edit_file
|
|
8
|
-
- shell
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
# Database Operations — Domain Knowledge
|
|
12
|
-
|
|
13
|
-
This skill teaches you database design, query optimization, and safe migration practices. Study this to make good data modeling decisions.
|
|
14
|
-
|
|
15
|
-
## Schema Design Principles
|
|
16
|
-
|
|
17
|
-
### Normalization Rules
|
|
18
|
-
- **1NF**: Atomic values, no repeating groups
|
|
19
|
-
- **2NF**: No partial dependencies on composite keys
|
|
20
|
-
- **3NF**: No transitive dependencies
|
|
21
|
-
|
|
22
|
-
### When to Denormalize
|
|
23
|
-
| Situation | Denormalize? | Technique |
|
|
24
|
-
|-----------|-------------|-----------|
|
|
25
|
-
| Read-heavy, write-rare | Yes | Materialized view / computed column |
|
|
26
|
-
| Reporting/analytics | Yes | Star schema / denormalized table |
|
|
27
|
-
| Real-time dashboard | Yes | Pre-aggregated cache |
|
|
28
|
-
| OLTP with consistency needs | No | Keep normalized |
|
|
29
|
-
|
|
30
|
-
## Query Optimization
|
|
31
|
-
|
|
32
|
-
### Indexing Decision Framework
|
|
33
|
-
| Query pattern | Index type |
|
|
34
|
-
|---------------|------------|
|
|
35
|
-
| `WHERE col = value` | B-tree index on col |
|
|
36
|
-
| `WHERE col1 = X AND col2 = Y` | Composite index (col1, col2) |
|
|
37
|
-
| `WHERE col LIKE 'prefix%'` | B-tree (prefix only) |
|
|
38
|
-
| `ORDER BY col` | Index on col |
|
|
39
|
-
| `WHERE col IN (...)` | B-tree index on col |
|
|
40
|
-
| Full-text search | GIN / Full-text index |
|
|
41
|
-
|
|
42
|
-
### Performance Diagnosis
|
|
43
|
-
1. `EXPLAIN ANALYZE` the slow query
|
|
44
|
-
2. Look for: Seq Scan (missing index), Nested Loop (N+1), Sort (missing index)
|
|
45
|
-
3. Add index → re-explain → verify improvement
|
|
46
|
-
|
|
47
|
-
### Common Performance Issues
|
|
48
|
-
| Problem | Symptom | Fix |
|
|
49
|
-
|---------|---------|-----|
|
|
50
|
-
| N+1 queries | Many identical queries | Eager loading / JOIN |
|
|
51
|
-
| Missing index | Seq Scan on large table | Add appropriate index |
|
|
52
|
-
| Over-fetching | SELECT * on wide table | Select specific columns |
|
|
53
|
-
| Lock contention | Timeout errors | Shorter transactions |
|
|
54
|
-
|
|
55
|
-
## Migration Safety
|
|
56
|
-
|
|
57
|
-
### Safe Operations (can run anytime)
|
|
58
|
-
- Add nullable column
|
|
59
|
-
- Add index CONCURRENTLY
|
|
60
|
-
- Create new table
|
|
61
|
-
- Add constraint with NOT VALID
|
|
62
|
-
|
|
63
|
-
### Dangerous Operations (need careful planning)
|
|
64
|
-
| Operation | Risk | Safe approach |
|
|
65
|
-
|-----------|------|---------------|
|
|
66
|
-
| Drop column | Data loss | Deploy code first, drop later |
|
|
67
|
-
| Rename column | Breaks queries | Add new, migrate, drop old |
|
|
68
|
-
| Change type | Data corruption | Add new column, backfill, swap |
|
|
69
|
-
| Add NOT NULL | Fails on existing nulls | Backfill first, then constrain |
|
|
70
|
-
|
|
71
|
-
## ORM vs Raw SQL
|
|
72
|
-
|
|
73
|
-
| Use ORM when... | Use Raw SQL when... |
|
|
74
|
-
|-----------------|---------------------|
|
|
75
|
-
| Standard CRUD | Complex aggregations |
|
|
76
|
-
| Migrations | Performance-critical queries |
|
|
77
|
-
| Type safety needed | Database-specific features |
|
|
78
|
-
| Rapid prototyping | Bulk operations |
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: frontend-bootstrap
|
|
3
|
-
description: Bootstrap full frontend projects from Figma and product requirements
|
|
4
|
-
tools:
|
|
5
|
-
- read_file
|
|
6
|
-
- write_file
|
|
7
|
-
- edit_file
|
|
8
|
-
- glob
|
|
9
|
-
- grep
|
|
10
|
-
- ls
|
|
11
|
-
- shell
|
|
12
|
-
---
|
|
13
|
-
|
|
14
|
-
# Frontend Bootstrap from Figma
|
|
15
|
-
|
|
16
|
-
Use this skill when the goal is to turn a prototype into a complete frontend foundation quickly.
|
|
17
|
-
|
|
18
|
-
## Outcome Targets
|
|
19
|
-
|
|
20
|
-
- Deliver a runnable frontend scaffold with routing, layout, and core pages.
|
|
21
|
-
- Generate reusable UI primitives before page-specific components.
|
|
22
|
-
- Apply consistent styling through design tokens and theme variables.
|
|
23
|
-
- Keep architecture ready for backend integration.
|
|
24
|
-
|
|
25
|
-
## Figma-to-Code Workflow
|
|
26
|
-
|
|
27
|
-
1. Map screens and flows:
|
|
28
|
-
- Identify all top-level screens in the prototype.
|
|
29
|
-
- Capture navigation structure and page hierarchy.
|
|
30
|
-
- Note critical interaction states (loading, empty, error, success).
|
|
31
|
-
|
|
32
|
-
2. Extract design system:
|
|
33
|
-
- Color palette, typography scale, spacing scale, border radius, shadow set.
|
|
34
|
-
- Component variants for button, input, select, table, modal, card, badge, tabs.
|
|
35
|
-
- Breakpoints and responsive behavior.
|
|
36
|
-
|
|
37
|
-
3. Plan project structure:
|
|
38
|
-
- `src/app` or `src/pages` for routes/screens.
|
|
39
|
-
- `src/components/ui` for primitives.
|
|
40
|
-
- `src/components/features` for domain components.
|
|
41
|
-
- `src/styles` for tokens/theme/global styles.
|
|
42
|
-
- `src/lib` for utilities and configuration.
|
|
43
|
-
|
|
44
|
-
4. Generate in layers:
|
|
45
|
-
- First: tokens/theme + base layout + routes.
|
|
46
|
-
- Second: UI primitives and variants.
|
|
47
|
-
- Third: screen composition using primitives.
|
|
48
|
-
- Fourth: stubs for API services and typed contracts.
|
|
49
|
-
|
|
50
|
-
5. Validate consistency:
|
|
51
|
-
- Verify token usage over hardcoded values.
|
|
52
|
-
- Verify responsive layout across mobile/tablet/desktop.
|
|
53
|
-
- Verify accessibility basics: semantic roles, labels, focus, contrast.
|
|
54
|
-
|
|
55
|
-
## Heuristics for Common Elements
|
|
56
|
-
|
|
57
|
-
- Table-heavy screens:
|
|
58
|
-
- Create reusable `DataTable` with column config, pagination, loading and empty states.
|
|
59
|
-
- Form-heavy screens:
|
|
60
|
-
- Create form field wrappers with validation message and helper text support.
|
|
61
|
-
- Modal-heavy flows:
|
|
62
|
-
- Standardize modal shell, close behavior, keyboard handling, and action footer.
|
|
63
|
-
- Dashboard screens:
|
|
64
|
-
- Prioritize layout grid and card primitives before chart wiring.
|
|
65
|
-
|
|
66
|
-
## Integration Readiness
|
|
67
|
-
|
|
68
|
-
- Keep API and data fetching behind dedicated service/hooks layers.
|
|
69
|
-
- Use mock data adapters initially to unblock UI.
|
|
70
|
-
- Preserve clear boundaries so backend integration only replaces adapters and endpoints.
|
|
71
|
-
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: react-patterns
|
|
3
|
-
description: React component patterns and best practices
|
|
4
|
-
tools:
|
|
5
|
-
- read_file
|
|
6
|
-
- write_file
|
|
7
|
-
- edit_file
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
# React Patterns — Domain Knowledge
|
|
11
|
-
|
|
12
|
-
This skill teaches you React best practices, component architecture, and performance patterns. Study this to write idiomatic React code.
|
|
13
|
-
|
|
14
|
-
## Component Architecture Decision Tree
|
|
15
|
-
|
|
16
|
-
| Need | Pattern | Why |
|
|
17
|
-
|------|---------|-----|
|
|
18
|
-
| Simple display | Functional component | No state needed |
|
|
19
|
-
| Local state | useState/useReducer | Component-level reactivity |
|
|
20
|
-
| Shared state | Context + useContext | Cross-component without prop drilling |
|
|
21
|
-
| Server data | React Query / SWR | Cache, refetch, loading states |
|
|
22
|
-
| Side effects | useEffect with cleanup | Subscriptions, timers, API calls |
|
|
23
|
-
| Reusable logic | Custom hooks | Extract and share behavior |
|
|
24
|
-
|
|
25
|
-
## Component Patterns
|
|
26
|
-
|
|
27
|
-
### Functional Components (always prefer)
|
|
28
|
-
```tsx
|
|
29
|
-
interface Props {
|
|
30
|
-
title: string;
|
|
31
|
-
onClick?: () => void;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export function MyComponent({ title, onClick }: Props) {
|
|
35
|
-
return <button onClick={onClick}>{title}</button>;
|
|
36
|
-
}
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
### Custom Hooks (extract reusable logic)
|
|
40
|
-
```tsx
|
|
41
|
-
function useCounter(initial = 0) {
|
|
42
|
-
const [count, setCount] = useState(initial);
|
|
43
|
-
const increment = useCallback(() => setCount(c => c + 1), []);
|
|
44
|
-
return { count, increment };
|
|
45
|
-
}
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
### Composition over Inheritance
|
|
49
|
-
- Use `children` prop for flexible layouts
|
|
50
|
-
- Use render props for shared behavior
|
|
51
|
-
- Use compound components for related UI (Tabs/Tab, Select/Option)
|
|
52
|
-
|
|
53
|
-
## Performance Rules
|
|
54
|
-
|
|
55
|
-
| Problem | Solution | When |
|
|
56
|
-
|---------|----------|------|
|
|
57
|
-
| Expensive calc re-runs | `useMemo(() => calc, [deps])` | calc takes >1ms |
|
|
58
|
-
| Callback causes re-render | `useCallback(fn, [deps])` | Passed to memoized child |
|
|
59
|
-
| Component re-renders unnecessarily | `React.memo(Component)` | Props rarely change |
|
|
60
|
-
| Large bundle | `React.lazy(() => import(...))` | Route-level splitting |
|
|
61
|
-
| Long list | Virtualization (react-window) | 100+ items |
|
|
62
|
-
|
|
63
|
-
## Anti-Patterns to Avoid
|
|
64
|
-
|
|
65
|
-
1. **State for derived data** — Compute from existing state instead of storing separately
|
|
66
|
-
2. **useEffect for transforms** — Transform during render, not in effects
|
|
67
|
-
3. **Index as key** — Use stable IDs from data, not array index
|
|
68
|
-
4. **Nested ternaries in JSX** — Extract to variables or early returns
|
|
69
|
-
5. **Prop drilling 3+ levels** — Use Context or composition
|
|
70
|
-
|
|
71
|
-
## Accessibility Checklist
|
|
72
|
-
|
|
73
|
-
- Semantic HTML (`button` not `div onClick`)
|
|
74
|
-
- ARIA labels for icon-only buttons
|
|
75
|
-
- Keyboard navigation (Tab, Enter, Escape)
|
|
76
|
-
- Focus management after modals/dialogs
|
|
77
|
-
- Color contrast (4.5:1 minimum)
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: testing-strategies
|
|
3
|
-
description: Testing patterns and strategies
|
|
4
|
-
tools:
|
|
5
|
-
- read_file
|
|
6
|
-
- write_file
|
|
7
|
-
- edit_file
|
|
8
|
-
- shell
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
# Testing Strategies — Domain Knowledge
|
|
12
|
-
|
|
13
|
-
This skill teaches you how to write effective tests. Study this to learn what to test, how to structure tests, and when to use different testing approaches.
|
|
14
|
-
|
|
15
|
-
## Testing Pyramid
|
|
16
|
-
|
|
17
|
-
| Level | Speed | Count | Coverage |
|
|
18
|
-
|-------|-------|-------|----------|
|
|
19
|
-
| Unit | Fast (ms) | Many | Functions, classes, utils |
|
|
20
|
-
| Integration | Medium (s) | Moderate | API routes, DB queries, services |
|
|
21
|
-
| E2E | Slow (s-min) | Few | Critical user flows only |
|
|
22
|
-
|
|
23
|
-
## The AAA Pattern (ALWAYS follow this)
|
|
24
|
-
|
|
25
|
-
```typescript
|
|
26
|
-
test('should [behavior] when [condition]', () => {
|
|
27
|
-
// Arrange — set up the test
|
|
28
|
-
const calculator = new Calculator();
|
|
29
|
-
|
|
30
|
-
// Act — perform the action
|
|
31
|
-
const result = calculator.add(2, 3);
|
|
32
|
-
|
|
33
|
-
// Assert — verify the result
|
|
34
|
-
expect(result).toBe(5);
|
|
35
|
-
});
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
## What to Test (Decision Framework)
|
|
39
|
-
|
|
40
|
-
| Code type | Test approach | Priority |
|
|
41
|
-
|-----------|---------------|----------|
|
|
42
|
-
| Pure functions | Unit test with edge cases | HIGH |
|
|
43
|
-
| API endpoints | Integration test with real DB | HIGH |
|
|
44
|
-
| UI components | Render + interaction tests | MEDIUM |
|
|
45
|
-
| Config/setup | Smoke test (does it load?) | LOW |
|
|
46
|
-
| External APIs | Mock + contract test | MEDIUM |
|
|
47
|
-
| Error paths | Unit test thrown errors | HIGH |
|
|
48
|
-
|
|
49
|
-
## Test Naming Convention
|
|
50
|
-
|
|
51
|
-
- `should [expected behavior] when [condition]`
|
|
52
|
-
- `[method] returns [result] for [input]`
|
|
53
|
-
- `throws [error] when [invalid input]`
|
|
54
|
-
|
|
55
|
-
## Mocking Rules
|
|
56
|
-
|
|
57
|
-
| Mock when... | Don't mock when... |
|
|
58
|
-
|-------------|-------------------|
|
|
59
|
-
| External API calls | Core business logic |
|
|
60
|
-
| Database in unit tests | Database in integration tests |
|
|
61
|
-
| Time (Date.now, timers) | Simple utility functions |
|
|
62
|
-
| Random values | Data transformations |
|
|
63
|
-
| File system in CI | File system in integration |
|
|
64
|
-
|
|
65
|
-
## Running Tests
|
|
66
|
-
|
|
67
|
-
- `npm test` or `npx jest` — run all tests
|
|
68
|
-
- `npm test -- --watch` — watch mode
|
|
69
|
-
- `npm test -- --coverage` — coverage report
|
|
70
|
-
- `npm test -- path/to/file` — run specific file
|
|
71
|
-
- `npx jest --testPathPattern="pattern"` — filter by pattern
|
|
72
|
-
|
|
73
|
-
## Common Mistakes
|
|
74
|
-
|
|
75
|
-
1. **Testing implementation, not behavior** — Test WHAT it does, not HOW
|
|
76
|
-
2. **Shared mutable state between tests** — Reset in beforeEach
|
|
77
|
-
3. **Not testing error cases** — Happy path + error paths
|
|
78
|
-
4. **Brittle snapshot tests** — Only snapshot stable, small components
|
|
79
|
-
5. **Skipping async cleanup** — Always await and clean up promises/timers
|