sdd-mcp-server 1.8.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +97 -41
- package/dist/cli/install-skills.d.ts +53 -0
- package/dist/cli/install-skills.js +171 -0
- package/dist/cli/install-skills.js.map +1 -0
- package/dist/index.js +140 -122
- package/dist/index.js.map +1 -1
- package/dist/skills/SkillManager.d.ts +69 -0
- package/dist/skills/SkillManager.js +138 -0
- package/dist/skills/SkillManager.js.map +1 -0
- package/package.json +6 -3
- package/skills/sdd-commit/SKILL.md +285 -0
- package/skills/sdd-design/SKILL.md +262 -0
- package/skills/sdd-implement/SKILL.md +281 -0
- package/skills/sdd-requirements/SKILL.md +140 -0
- package/skills/sdd-steering/SKILL.md +225 -0
- package/skills/sdd-steering-custom/SKILL.md +211 -0
- package/skills/sdd-tasks/SKILL.md +233 -0
- package/skills/simple-task/SKILL.md +148 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Descriptor for an SDD skill
|
|
3
|
+
*/
|
|
4
|
+
export interface SkillDescriptor {
|
|
5
|
+
/** Skill name (e.g., 'sdd-requirements') */
|
|
6
|
+
name: string;
|
|
7
|
+
/** Brief description of the skill */
|
|
8
|
+
description: string;
|
|
9
|
+
/** Path to the skill directory */
|
|
10
|
+
path: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Result of skill installation
|
|
14
|
+
*/
|
|
15
|
+
export interface InstallResult {
|
|
16
|
+
/** Successfully installed skills */
|
|
17
|
+
installed: string[];
|
|
18
|
+
/** Failed installations with error details */
|
|
19
|
+
failed: Array<{
|
|
20
|
+
name: string;
|
|
21
|
+
error: string;
|
|
22
|
+
}>;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Parsed skill metadata from SKILL.md frontmatter
|
|
26
|
+
*/
|
|
27
|
+
export interface SkillMetadata {
|
|
28
|
+
name?: string;
|
|
29
|
+
description?: string;
|
|
30
|
+
[key: string]: unknown;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Manages SDD skills - discovery, listing, and installation
|
|
34
|
+
*
|
|
35
|
+
* Skills are markdown files in the skills directory that provide
|
|
36
|
+
* guidance for Claude Code agent interactions.
|
|
37
|
+
*/
|
|
38
|
+
export declare class SkillManager {
|
|
39
|
+
private readonly skillsPath;
|
|
40
|
+
/**
|
|
41
|
+
* Create a new SkillManager
|
|
42
|
+
* @param skillsPath - Path to the skills directory in the package
|
|
43
|
+
*/
|
|
44
|
+
constructor(skillsPath: string);
|
|
45
|
+
/**
|
|
46
|
+
* List all available skills
|
|
47
|
+
* @returns Array of skill descriptors
|
|
48
|
+
*/
|
|
49
|
+
listSkills(): Promise<SkillDescriptor[]>;
|
|
50
|
+
/**
|
|
51
|
+
* Get the path to a specific skill
|
|
52
|
+
* @param skillName - Name of the skill
|
|
53
|
+
* @returns Path to the skill directory
|
|
54
|
+
* @throws Error if skill not found
|
|
55
|
+
*/
|
|
56
|
+
getSkillPath(skillName: string): Promise<string>;
|
|
57
|
+
/**
|
|
58
|
+
* Install skills to a target directory
|
|
59
|
+
* @param targetPath - Target directory (e.g., /project/.claude/skills)
|
|
60
|
+
* @returns Installation result with success and failure details
|
|
61
|
+
*/
|
|
62
|
+
installSkills(targetPath: string): Promise<InstallResult>;
|
|
63
|
+
/**
|
|
64
|
+
* Parse YAML frontmatter from SKILL.md content
|
|
65
|
+
* @param content - Content of SKILL.md file
|
|
66
|
+
* @returns Parsed metadata
|
|
67
|
+
*/
|
|
68
|
+
parseSkillMetadata(content: string): SkillMetadata;
|
|
69
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
/**
|
|
4
|
+
* Manages SDD skills - discovery, listing, and installation
|
|
5
|
+
*
|
|
6
|
+
* Skills are markdown files in the skills directory that provide
|
|
7
|
+
* guidance for Claude Code agent interactions.
|
|
8
|
+
*/
|
|
9
|
+
export class SkillManager {
|
|
10
|
+
skillsPath;
|
|
11
|
+
/**
|
|
12
|
+
* Create a new SkillManager
|
|
13
|
+
* @param skillsPath - Path to the skills directory in the package
|
|
14
|
+
*/
|
|
15
|
+
constructor(skillsPath) {
|
|
16
|
+
this.skillsPath = skillsPath;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* List all available skills
|
|
20
|
+
* @returns Array of skill descriptors
|
|
21
|
+
*/
|
|
22
|
+
async listSkills() {
|
|
23
|
+
const skills = [];
|
|
24
|
+
try {
|
|
25
|
+
const entries = await fs.promises.readdir(this.skillsPath, { withFileTypes: true });
|
|
26
|
+
for (const entry of entries) {
|
|
27
|
+
if (entry.isDirectory()) {
|
|
28
|
+
const skillDir = entry.name;
|
|
29
|
+
const skillMdPath = path.join(this.skillsPath, skillDir, 'SKILL.md');
|
|
30
|
+
try {
|
|
31
|
+
const content = await fs.promises.readFile(skillMdPath, 'utf-8');
|
|
32
|
+
const metadata = this.parseSkillMetadata(content);
|
|
33
|
+
skills.push({
|
|
34
|
+
name: metadata.name || skillDir,
|
|
35
|
+
description: metadata.description || '',
|
|
36
|
+
path: path.join(this.skillsPath, skillDir),
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
// Skip directories without SKILL.md
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
// Return empty array if skills directory doesn't exist
|
|
48
|
+
return [];
|
|
49
|
+
}
|
|
50
|
+
return skills;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Get the path to a specific skill
|
|
54
|
+
* @param skillName - Name of the skill
|
|
55
|
+
* @returns Path to the skill directory
|
|
56
|
+
* @throws Error if skill not found
|
|
57
|
+
*/
|
|
58
|
+
async getSkillPath(skillName) {
|
|
59
|
+
const skillPath = path.join(this.skillsPath, skillName);
|
|
60
|
+
if (!fs.existsSync(skillPath)) {
|
|
61
|
+
throw new Error(`Skill "${skillName}" not found`);
|
|
62
|
+
}
|
|
63
|
+
return skillPath;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Install skills to a target directory
|
|
67
|
+
* @param targetPath - Target directory (e.g., /project/.claude/skills)
|
|
68
|
+
* @returns Installation result with success and failure details
|
|
69
|
+
*/
|
|
70
|
+
async installSkills(targetPath) {
|
|
71
|
+
const result = {
|
|
72
|
+
installed: [],
|
|
73
|
+
failed: [],
|
|
74
|
+
};
|
|
75
|
+
// Create target directory
|
|
76
|
+
await fs.promises.mkdir(targetPath, { recursive: true });
|
|
77
|
+
try {
|
|
78
|
+
const entries = await fs.promises.readdir(this.skillsPath, { withFileTypes: true });
|
|
79
|
+
for (const entry of entries) {
|
|
80
|
+
if (!entry.isDirectory())
|
|
81
|
+
continue;
|
|
82
|
+
const skillName = entry.name;
|
|
83
|
+
const sourceDir = path.join(this.skillsPath, skillName);
|
|
84
|
+
const destDir = path.join(targetPath, skillName);
|
|
85
|
+
try {
|
|
86
|
+
// Create skill destination directory
|
|
87
|
+
await fs.promises.mkdir(destDir, { recursive: true });
|
|
88
|
+
// Copy all files in the skill directory
|
|
89
|
+
const files = await fs.promises.readdir(sourceDir, { withFileTypes: true });
|
|
90
|
+
for (const file of files) {
|
|
91
|
+
if (!file.isDirectory()) {
|
|
92
|
+
const sourceFile = path.join(sourceDir, file.name);
|
|
93
|
+
const destFile = path.join(destDir, file.name);
|
|
94
|
+
await fs.promises.copyFile(sourceFile, destFile);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
result.installed.push(skillName);
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
result.failed.push({
|
|
101
|
+
name: skillName,
|
|
102
|
+
error: error instanceof Error ? error.message : String(error),
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
// Return current result if reading skills directory fails
|
|
109
|
+
}
|
|
110
|
+
return result;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Parse YAML frontmatter from SKILL.md content
|
|
114
|
+
* @param content - Content of SKILL.md file
|
|
115
|
+
* @returns Parsed metadata
|
|
116
|
+
*/
|
|
117
|
+
parseSkillMetadata(content) {
|
|
118
|
+
const metadata = {};
|
|
119
|
+
// Match YAML frontmatter between --- delimiters
|
|
120
|
+
const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
121
|
+
if (!frontmatterMatch) {
|
|
122
|
+
return metadata;
|
|
123
|
+
}
|
|
124
|
+
const frontmatter = frontmatterMatch[1];
|
|
125
|
+
// Simple YAML parsing for key: value pairs
|
|
126
|
+
const lines = frontmatter.split('\n');
|
|
127
|
+
for (const line of lines) {
|
|
128
|
+
const colonIndex = line.indexOf(':');
|
|
129
|
+
if (colonIndex > 0) {
|
|
130
|
+
const key = line.slice(0, colonIndex).trim();
|
|
131
|
+
const value = line.slice(colonIndex + 1).trim();
|
|
132
|
+
metadata[key] = value;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return metadata;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=SkillManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SkillManager.js","sourceRoot":"","sources":["../../src/skills/SkillManager.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sdd-mcp-server",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "MCP server for spec-driven development workflows across AI-agent CLIs and IDEs",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"sdd-mcp-server": "mcp-server.js",
|
|
8
|
-
"sdd-mcp": "dist/index.js"
|
|
8
|
+
"sdd-mcp": "dist/index.js",
|
|
9
|
+
"sdd-install-skills": "dist/cli/install-skills.js"
|
|
9
10
|
},
|
|
10
11
|
"type": "module",
|
|
11
12
|
"files": [
|
|
12
13
|
"dist/**/*",
|
|
14
|
+
"skills/**/*",
|
|
13
15
|
"mcp-server.js",
|
|
14
16
|
"documentGenerator.js",
|
|
15
17
|
"specGenerator.js",
|
|
@@ -66,7 +68,8 @@
|
|
|
66
68
|
"inversify": "^6.0.2",
|
|
67
69
|
"os-locale": "^6.0.2",
|
|
68
70
|
"reflect-metadata": "^0.2.2",
|
|
69
|
-
"uuid": "^10.0.0"
|
|
71
|
+
"uuid": "^10.0.0",
|
|
72
|
+
"zod": "^3.23.8"
|
|
70
73
|
},
|
|
71
74
|
"devDependencies": {
|
|
72
75
|
"@types/esprima": "^4.0.6",
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sdd-commit
|
|
3
|
+
description: Guide commit message and PR creation for SDD workflow. Use when committing changes, creating pull requests, or documenting changes. Invoked via /sdd-commit.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# SDD Commit & PR Guidelines
|
|
7
|
+
|
|
8
|
+
Create clear, consistent commit messages and pull requests that document changes effectively.
|
|
9
|
+
|
|
10
|
+
## Commit Message Format
|
|
11
|
+
|
|
12
|
+
Follow the Conventional Commits specification:
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
<type>(<scope>): <subject>
|
|
16
|
+
|
|
17
|
+
[optional body]
|
|
18
|
+
|
|
19
|
+
[optional footer(s)]
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### Type Prefixes
|
|
23
|
+
|
|
24
|
+
| Type | When to Use | Example |
|
|
25
|
+
|------|-------------|---------|
|
|
26
|
+
| `feat` | New feature | `feat(auth): add JWT refresh token` |
|
|
27
|
+
| `fix` | Bug fix | `fix(api): handle null user response` |
|
|
28
|
+
| `docs` | Documentation only | `docs(readme): update installation steps` |
|
|
29
|
+
| `style` | Formatting, no code change | `style(lint): fix linter warnings` |
|
|
30
|
+
| `refactor` | Code change, no new feature or fix | `refactor(user): extract validation logic` |
|
|
31
|
+
| `perf` | Performance improvement | `perf(query): add index for user lookup` |
|
|
32
|
+
| `test` | Adding/updating tests | `test(auth): add login failure tests` |
|
|
33
|
+
| `build` | Build system changes | `build(deps): update dependencies` |
|
|
34
|
+
| `ci` | CI/CD changes | `ci(github): add test workflow` |
|
|
35
|
+
| `chore` | Other changes | `chore(deps): bump lodash version` |
|
|
36
|
+
| `revert` | Revert previous commit | `revert: feat(auth): add JWT refresh` |
|
|
37
|
+
|
|
38
|
+
### Scope
|
|
39
|
+
|
|
40
|
+
The scope should indicate the area affected:
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
feat(auth): # Authentication module
|
|
44
|
+
fix(api/users): # Users API endpoint
|
|
45
|
+
docs(readme): # README file
|
|
46
|
+
test(e2e): # End-to-end tests
|
|
47
|
+
refactor(db): # Database layer
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Subject Line
|
|
51
|
+
|
|
52
|
+
- Use imperative mood: "add" not "added" or "adds"
|
|
53
|
+
- Don't capitalize first letter
|
|
54
|
+
- No period at the end
|
|
55
|
+
- Max 50 characters
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
# GOOD
|
|
59
|
+
feat(auth): add password reset flow
|
|
60
|
+
fix(cart): prevent duplicate items
|
|
61
|
+
|
|
62
|
+
# BAD
|
|
63
|
+
feat(auth): Added password reset flow.
|
|
64
|
+
fix(cart): Fixes the duplicate items bug
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Body (Optional)
|
|
68
|
+
|
|
69
|
+
Use for explaining:
|
|
70
|
+
- **What** changed and **why**
|
|
71
|
+
- Breaking changes
|
|
72
|
+
- Related issues
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
feat(auth): add multi-factor authentication
|
|
76
|
+
|
|
77
|
+
Implement TOTP-based 2FA for enhanced security.
|
|
78
|
+
Users can now enable 2FA from their profile settings.
|
|
79
|
+
|
|
80
|
+
- Add TOTP secret generation
|
|
81
|
+
- Add QR code for authenticator apps
|
|
82
|
+
- Add backup codes for recovery
|
|
83
|
+
|
|
84
|
+
Closes #123
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Footer (Optional)
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
BREAKING CHANGE: API endpoint changed from /users to /api/v1/users
|
|
91
|
+
|
|
92
|
+
Refs: #123, #456
|
|
93
|
+
Co-authored-by: Name <email@example.com>
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Pull Request Template
|
|
97
|
+
|
|
98
|
+
```markdown
|
|
99
|
+
## Summary
|
|
100
|
+
<!-- 1-3 bullet points describing the changes -->
|
|
101
|
+
- Add user authentication with JWT
|
|
102
|
+
- Implement password reset flow
|
|
103
|
+
- Add comprehensive test coverage
|
|
104
|
+
|
|
105
|
+
## Motivation
|
|
106
|
+
<!-- Why is this change needed? -->
|
|
107
|
+
Users need secure authentication to access protected resources.
|
|
108
|
+
|
|
109
|
+
## Changes
|
|
110
|
+
<!-- Detailed list of changes -->
|
|
111
|
+
### Added
|
|
112
|
+
- `AuthService` for handling authentication logic
|
|
113
|
+
- `JWTProvider` for token generation/validation
|
|
114
|
+
- Unit and integration tests for auth flow
|
|
115
|
+
|
|
116
|
+
### Changed
|
|
117
|
+
- Updated `UserController` to use AuthService
|
|
118
|
+
- Modified API routes to require authentication
|
|
119
|
+
|
|
120
|
+
### Removed
|
|
121
|
+
- Deprecated session-based authentication
|
|
122
|
+
|
|
123
|
+
## Testing
|
|
124
|
+
<!-- How was this tested? -->
|
|
125
|
+
- [x] Unit tests pass
|
|
126
|
+
- [x] Integration tests pass
|
|
127
|
+
- [x] Manual testing completed
|
|
128
|
+
- [ ] E2E tests (pending)
|
|
129
|
+
|
|
130
|
+
## Screenshots
|
|
131
|
+
<!-- If applicable -->
|
|
132
|
+
|
|
133
|
+
## Checklist
|
|
134
|
+
- [x] Code follows project style guidelines
|
|
135
|
+
- [x] Tests added/updated
|
|
136
|
+
- [x] Documentation updated
|
|
137
|
+
- [x] No breaking changes (or documented)
|
|
138
|
+
- [x] Security considerations reviewed
|
|
139
|
+
|
|
140
|
+
## Related Issues
|
|
141
|
+
Closes #123
|
|
142
|
+
Refs #456
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Commit Best Practices
|
|
146
|
+
|
|
147
|
+
### Atomic Commits
|
|
148
|
+
Each commit should be one logical change:
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
# GOOD: Separate commits for separate changes
|
|
152
|
+
git commit -m "feat(user): add email validation"
|
|
153
|
+
git commit -m "test(user): add email validation tests"
|
|
154
|
+
|
|
155
|
+
# BAD: Multiple unrelated changes
|
|
156
|
+
git commit -m "add email validation, fix bug, update docs"
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Commit Frequency
|
|
160
|
+
- Commit when a logical unit is complete
|
|
161
|
+
- Don't commit broken code
|
|
162
|
+
- Small, frequent commits are better than large, infrequent ones
|
|
163
|
+
|
|
164
|
+
### Commit Message Examples
|
|
165
|
+
|
|
166
|
+
#### Feature
|
|
167
|
+
```
|
|
168
|
+
feat(cart): add quantity update functionality
|
|
169
|
+
|
|
170
|
+
Allow users to update item quantities directly from the cart.
|
|
171
|
+
Includes optimistic UI updates and error handling.
|
|
172
|
+
|
|
173
|
+
- Add updateQuantity method to CartService
|
|
174
|
+
- Add quantity input component
|
|
175
|
+
- Add debounced API calls
|
|
176
|
+
|
|
177
|
+
Closes #234
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
#### Bug Fix
|
|
181
|
+
```
|
|
182
|
+
fix(auth): prevent session fixation attack
|
|
183
|
+
|
|
184
|
+
Regenerate session ID after successful login to prevent
|
|
185
|
+
session fixation attacks.
|
|
186
|
+
|
|
187
|
+
Security: OWASP A7 - Identification and Authentication Failures
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
#### Refactor
|
|
191
|
+
```
|
|
192
|
+
refactor(api): extract common error handling
|
|
193
|
+
|
|
194
|
+
Move error handling logic to middleware for consistency
|
|
195
|
+
across all API endpoints.
|
|
196
|
+
|
|
197
|
+
- Create ErrorHandlerMiddleware
|
|
198
|
+
- Add custom error classes
|
|
199
|
+
- Update all controllers to throw custom errors
|
|
200
|
+
|
|
201
|
+
No functional changes.
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
#### Breaking Change
|
|
205
|
+
```
|
|
206
|
+
feat(api)!: change user endpoint response format
|
|
207
|
+
|
|
208
|
+
BREAKING CHANGE: The /api/users endpoint now returns
|
|
209
|
+
a paginated response instead of an array.
|
|
210
|
+
|
|
211
|
+
Before:
|
|
212
|
+
[{ id: 1, name: "John" }, ...]
|
|
213
|
+
|
|
214
|
+
After:
|
|
215
|
+
{
|
|
216
|
+
data: [{ id: 1, name: "John" }, ...],
|
|
217
|
+
pagination: { page: 1, total: 100 }
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
Migration: Update all clients to handle the new response format.
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
## Branch Naming
|
|
224
|
+
|
|
225
|
+
```
|
|
226
|
+
<type>/<ticket>-<description>
|
|
227
|
+
|
|
228
|
+
Examples:
|
|
229
|
+
feature/AUTH-123-jwt-authentication
|
|
230
|
+
bugfix/CART-456-duplicate-items
|
|
231
|
+
hotfix/PROD-789-security-patch
|
|
232
|
+
chore/update-dependencies
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
## Git Workflow
|
|
236
|
+
|
|
237
|
+
### Before Committing
|
|
238
|
+
```bash
|
|
239
|
+
# Check status
|
|
240
|
+
git status
|
|
241
|
+
|
|
242
|
+
# Review changes
|
|
243
|
+
git diff
|
|
244
|
+
|
|
245
|
+
# Stage specific files
|
|
246
|
+
git add src/auth/
|
|
247
|
+
|
|
248
|
+
# Or stage all
|
|
249
|
+
git add -A
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### Creating Commit
|
|
253
|
+
```bash
|
|
254
|
+
# With message
|
|
255
|
+
git commit -m "feat(auth): add login endpoint"
|
|
256
|
+
|
|
257
|
+
# Open editor for longer message
|
|
258
|
+
git commit
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### Before PR
|
|
262
|
+
```bash
|
|
263
|
+
# Update from main
|
|
264
|
+
git fetch origin main
|
|
265
|
+
git rebase origin/main
|
|
266
|
+
|
|
267
|
+
# Run tests
|
|
268
|
+
{your test command} # e.g., npm test, pytest, cargo test, go test
|
|
269
|
+
|
|
270
|
+
# Push
|
|
271
|
+
git push origin feature/AUTH-123-jwt-auth
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
## Quality Checklist
|
|
275
|
+
|
|
276
|
+
- [ ] Commit message follows format
|
|
277
|
+
- [ ] Type prefix is appropriate
|
|
278
|
+
- [ ] Scope is specific
|
|
279
|
+
- [ ] Subject is imperative and concise
|
|
280
|
+
- [ ] Body explains why (if needed)
|
|
281
|
+
- [ ] Breaking changes documented
|
|
282
|
+
- [ ] Related issues linked
|
|
283
|
+
- [ ] Branch name follows convention
|
|
284
|
+
- [ ] Tests pass before commit
|
|
285
|
+
- [ ] PR description complete
|