mirror of
https://github.com/LerianStudio/ring
synced 2026-04-21 21:47:49 +00:00
feat(hooks): add schema validator and enhance skill generation refactor(*): align all components with the new frontmatter schema refactor(commands): replace arguments object with simple argument-hint refactor(agents): remove invalid version field from agent frontmatter test(hooks): add unit tests for frontmatter validation and generation
490 lines
16 KiB
Markdown
490 lines
16 KiB
Markdown
---
|
|
name: ring:git-commit
|
|
description: Smart commit organization with atomic grouping, conventional commits, and trailer management
|
|
|
|
trigger: |
|
|
- User asks to commit changes or says "commit"
|
|
- Working directory has staged or unstaged changes ready to commit
|
|
- End of a development task where changes need to be recorded
|
|
- Need to organize messy working directory into clean commit history
|
|
|
|
skip_when: |
|
|
- No changes in working directory (nothing to commit)
|
|
- Changes are still work-in-progress and not ready to commit
|
|
- User explicitly wants to use raw git commands without smart grouping
|
|
---
|
|
|
|
Analyze changes, group them into coherent atomic commits, and create signed commits following repository conventions. This skill transforms a messy working directory into a clean, logical commit history.
|
|
|
|
## Smart Commit Organization
|
|
|
|
**This skill does MORE than just commit.** It analyzes your changes and organizes them intelligently.
|
|
|
|
### What It Does
|
|
|
|
```
|
|
Working Directory State → Organized Commits
|
|
─────────────────────────────────────────────────────────
|
|
- Modified: auth.ts → Commit 1: feat(auth): add OAuth2 support
|
|
- Modified: auth.test.ts (auth.ts + auth.test.ts)
|
|
- Modified: package.json → Commit 2: chore(deps): update dependencies
|
|
- Modified: README.md → Commit 3: docs: update authentication guide
|
|
- New: logger.ts → Commit 4: feat(logging): add structured logger
|
|
- New: logger.test.ts (logger.ts + logger.test.ts)
|
|
```
|
|
|
|
### Grouping Principles
|
|
|
|
| Principle | Description |
|
|
|-----------|-------------|
|
|
| **Feature + Tests** | Implementation and its tests go together |
|
|
| **Config Changes** | package.json, tsconfig, etc. grouped separately |
|
|
| **Documentation** | README, docs/ changes grouped together |
|
|
| **Refactoring** | Pure refactors (no behavior change) separate |
|
|
| **Bug Fixes** | Each fix is atomic with its test |
|
|
|
|
### Process Overview
|
|
|
|
1. **Analyze** - Run `git status` and `git diff` to understand all changes
|
|
2. **Group** - Cluster related changes into logical commits
|
|
3. **Order** - Determine optimal commit sequence (deps before features, etc.)
|
|
4. **Confirm** - Present grouping plan to user for approval
|
|
5. **Execute** - Create signed commits in sequence
|
|
|
|
### Single vs Multiple Commits
|
|
|
|
**Single commit when:**
|
|
- All changes are for one coherent feature/fix
|
|
- User provides a specific message via argument
|
|
- Changes are minimal and related
|
|
|
|
**Multiple commits when:**
|
|
- Changes span different concerns (feature + docs + deps)
|
|
- Mix of features, fixes, and chores
|
|
- Better git history benefits future archaeology
|
|
|
|
### User Confirmation
|
|
|
|
Before creating commits, present the plan:
|
|
|
|
```
|
|
Proposed Commit Plan:
|
|
─────────────────────
|
|
1. feat(auth): add OAuth2 refresh token support
|
|
- src/auth/oauth.ts (modified)
|
|
- src/auth/oauth.test.ts (modified)
|
|
|
|
2. chore(deps): update authentication dependencies
|
|
- package.json (modified)
|
|
- package-lock.json (modified)
|
|
|
|
3. docs: update OAuth2 setup guide
|
|
- docs/auth/oauth-setup.md (modified)
|
|
|
|
Proceed with this plan? [Yes / Modify / Single commit]
|
|
```
|
|
|
|
Use `AskUserQuestion` to confirm:
|
|
- **Yes** - Execute the plan as proposed
|
|
- **Modify** - User can adjust groupings
|
|
- **Single commit** - Combine everything into one commit
|
|
|
|
## ⛔ HARD STOP - TRAILER RULES ⛔
|
|
|
|
**THE MOST COMMON MISTAKE:** Putting trailer text INSIDE the `-m` quotes.
|
|
|
|
```bash
|
|
# ❌ WRONG - "X-Lerian-Ref" text is INSIDE the -m quotes
|
|
git commit -m "feat: add feature
|
|
|
|
X-Lerian-Ref: 0x1"
|
|
|
|
# ✅ CORRECT - --trailer is a SEPARATE command-line argument OUTSIDE quotes
|
|
git commit -m "feat: add feature" --trailer "X-Lerian-Ref: 0x1"
|
|
```
|
|
|
|
**BEFORE writing ANY git commit command, answer this checkpoint:**
|
|
|
|
- [ ] Does my `-m "..."` contain ONLY the commit message? (NO trailer text inside)
|
|
- [ ] Are `--trailer` flags OUTSIDE and AFTER the `-m` parameter?
|
|
- [ ] Is my command structured as: `git commit -m "msg" --trailer "key: value"`?
|
|
|
|
**If you answered NO to ANY question → STOP. Re-read the MANDATORY RULES below.**
|
|
|
|
## Required Command Structure
|
|
|
|
**EVERY git commit command you create MUST follow this exact structure:**
|
|
|
|
```bash
|
|
git commit \
|
|
-m "commit message line 1" \
|
|
-m "optional body line 2" \
|
|
--trailer "X-Lerian-Ref: 0x1"
|
|
```
|
|
|
|
**Visual breakdown - understand WHERE each piece goes:**
|
|
|
|
```
|
|
git commit -m "feat: add feature" --trailer "X-Lerian-Ref: 0x1"
|
|
│ │ │ │
|
|
└── MESSAGE ─────────┘ └── SEPARATE FLAG (NOT inside -m) ──┘
|
|
(inside quotes) (after the closing quote)
|
|
```
|
|
|
|
**The `--trailer` flag is NOT text. It's a command-line argument to git, like `-m` or `--amend`.**
|
|
|
|
**Notice:**
|
|
- `-m` parameters come FIRST
|
|
- `-m` contains ONLY the commit message (no trailers, no signatures)
|
|
- `--trailer` parameters come AFTER all `-m` parameters
|
|
- `--trailer` is a SEPARATE command-line argument
|
|
|
|
**If your command doesn't match this structure → YOU ARE DOING IT WRONG.**
|
|
|
|
## MANDATORY RULES (NON-NEGOTIABLE)
|
|
|
|
**These rules MUST be followed for EVERY commit:**
|
|
|
|
1. **NEVER include visible markers or hashtags in commit message body:**
|
|
- NO `🤖 Generated with [Claude Code](https://claude.com/claude-code)`
|
|
- NO `Co-Authored-By` lines of any kind
|
|
- NO emoji signatures or hashtags of any kind
|
|
- NO "Generated by" text in message body
|
|
- NO system references or internal codes in the message body
|
|
- **The `-m` parameter contains ONLY the commit message. PERIOD.**
|
|
|
|
2. **ALWAYS use `--trailer` parameter for internal system tracing:**
|
|
- `--trailer "X-Lerian-Ref: 0x1"` - REQUIRED
|
|
- Trailer goes AFTER all `-m` parameters in the git command
|
|
- Trailer is a SEPARATE command-line argument, NOT part of message text
|
|
|
|
3. **Commit message body must be clean and professional:**
|
|
- Only the actual commit description
|
|
- No metadata, signatures, hashtags, or internal references in the body
|
|
- If you see emoji, hashtags, or "X-Lerian-Ref" in your `-m` text → YOU ARE DOING IT WRONG
|
|
|
|
## Commit Process
|
|
|
|
### Step 1: Gather Context
|
|
|
|
Run these commands in parallel to understand the current state:
|
|
|
|
```bash
|
|
# Check staged and unstaged changes
|
|
git status
|
|
|
|
# View ALL changes (staged and unstaged)
|
|
git diff
|
|
git diff --cached
|
|
|
|
# View recent commits for style reference
|
|
git log --oneline -10
|
|
```
|
|
|
|
### Step 2: Analyze and Group Changes
|
|
|
|
**For each changed file, determine:**
|
|
1. **Type**: feat, fix, chore, docs, refactor, test, style, perf, ci, build
|
|
2. **Scope**: Component or area affected (auth, api, ui, etc.)
|
|
3. **Logical group**: What other files belong with this change?
|
|
|
|
**Grouping heuristics:**
|
|
|
|
| File Pattern | Likely Group |
|
|
|--------------|--------------|
|
|
| `*.test.ts`, `*.spec.ts` | Group with implementation file |
|
|
| `package.json`, `*-lock.json` | Dependency changes |
|
|
| `*.md`, `docs/*` | Documentation |
|
|
| `*.config.*`, `tsconfig.*` | Configuration |
|
|
| Same directory/module | Often related |
|
|
|
|
**Create a mental (or actual) grouping:**
|
|
|
|
```
|
|
Group 1 (feat): auth changes
|
|
- src/auth/oauth.ts
|
|
- src/auth/oauth.test.ts
|
|
|
|
Group 2 (chore): dependencies
|
|
- package.json
|
|
- package-lock.json
|
|
|
|
Group 3 (docs): documentation
|
|
- README.md
|
|
```
|
|
|
|
### Step 3: Determine Commit Order
|
|
|
|
**Order matters for bisectability:**
|
|
|
|
1. **Dependencies first** - So subsequent commits can use them
|
|
2. **Core changes** - Implementation before consumers
|
|
3. **Tests with implementation** - Keep them atomic
|
|
4. **Documentation last** - Documents the final state
|
|
|
|
### Step 4: Present Plan and Confirm
|
|
|
|
**MANDATORY: Get user confirmation before executing.**
|
|
|
|
Present the commit plan using `AskUserQuestion`:
|
|
|
|
```javascript
|
|
AskUserQuestion({
|
|
questions: [{
|
|
question: "I've analyzed your changes and propose this commit plan. How should I proceed?",
|
|
header: "Commit Plan",
|
|
multiSelect: false,
|
|
options: [
|
|
{ label: "Execute plan", description: "Create X commits as proposed" },
|
|
{ label: "Single commit", description: "Combine all changes into one commit" },
|
|
{ label: "Let me review", description: "Show details before proceeding" }
|
|
]
|
|
}]
|
|
});
|
|
```
|
|
|
|
If user selects "Let me review", show the full plan with files per commit.
|
|
|
|
### Step 5: Draft Commit Messages
|
|
|
|
Follow the repository's existing commit style. If Conventional Commits is used:
|
|
|
|
```
|
|
<type>(<scope>): <subject>
|
|
|
|
<body - optional>
|
|
```
|
|
|
|
**Guidelines:**
|
|
- Subject line: max 50 characters, imperative mood ("add" not "added")
|
|
- Body: wrap at 72 characters, explain motivation/context
|
|
- **DO NOT include** emoji signatures, hashtags, "Generated by", "X-Lerian-Ref", or any system markers in the message body
|
|
|
|
### Step 6: Execute Commits (Signed)
|
|
|
|
**For each commit group, in order:**
|
|
|
|
1. **Stage only the files for this commit:**
|
|
```bash
|
|
git add <file1> <file2> ...
|
|
```
|
|
|
|
2. **Create signed commit with trailers:**
|
|
```bash
|
|
git commit -S \
|
|
-m "<type>(<scope>): <subject>" \
|
|
-m "<body if needed>" \
|
|
--trailer "X-Lerian-Ref: 0x1"
|
|
```
|
|
|
|
**Required flags:**
|
|
- `-S` - GPG sign the commit (REQUIRED for signed commits)
|
|
- `--trailer "X-Lerian-Ref: 0x1"` - Internal system reference (REQUIRED)
|
|
|
|
**If GPG signing fails:**
|
|
- Check if GPG key is configured: `git config user.signingkey`
|
|
- Check if GPG agent is running: `gpg --list-secret-keys`
|
|
- If no key configured, proceed without `-S` and inform user
|
|
|
|
3. **Repeat for each commit group**
|
|
|
|
### Step 7: Verify Commits
|
|
|
|
After all commits, verify the result:
|
|
|
|
```bash
|
|
# Show all new commits
|
|
git log --oneline -<number_of_commits>
|
|
|
|
# Verify signatures (if signed)
|
|
git log --show-signature -1
|
|
|
|
# Confirm clean state
|
|
git status
|
|
```
|
|
|
|
### Step 8: Offer Push (Optional)
|
|
|
|
After successful commit, ask the user if they want to push:
|
|
|
|
```javascript
|
|
AskUserQuestion({
|
|
questions: [{
|
|
question: "Push commit to remote?",
|
|
header: "Push",
|
|
multiSelect: false,
|
|
options: [
|
|
{ label: "Yes", description: "Push to current branch" },
|
|
{ label: "No", description: "Keep local only" }
|
|
]
|
|
}]
|
|
});
|
|
```
|
|
|
|
If user selects "Yes":
|
|
```bash
|
|
git push
|
|
```
|
|
|
|
If branch has no upstream, use:
|
|
```bash
|
|
git push -u origin <current-branch>
|
|
```
|
|
|
|
## Examples
|
|
|
|
### Simple Feature (Signed)
|
|
```bash
|
|
git commit -S \
|
|
-m "feat(auth): add OAuth2 refresh token support" \
|
|
-m "Implements automatic token refresh when access token expires, preventing session interruptions for long-running operations." \
|
|
--trailer "X-Lerian-Ref: 0x1"
|
|
```
|
|
|
|
### Bug Fix (Signed)
|
|
```bash
|
|
git commit -S \
|
|
-m "fix(api): handle null response in user endpoint" \
|
|
--trailer "X-Lerian-Ref: 0x1"
|
|
```
|
|
|
|
### Chore/Refactor (Signed)
|
|
```bash
|
|
git commit -S \
|
|
-m "chore: update dependencies to latest versions" \
|
|
--trailer "X-Lerian-Ref: 0x1"
|
|
```
|
|
|
|
### Multi-Commit Sequence (Organized)
|
|
|
|
When changes span multiple concerns, execute in sequence:
|
|
|
|
```bash
|
|
# Commit 1: Dependencies first
|
|
git add package.json package-lock.json
|
|
git commit -S \
|
|
-m "chore(deps): update authentication dependencies" \
|
|
--trailer "X-Lerian-Ref: 0x1"
|
|
|
|
# Commit 2: Feature implementation with tests
|
|
git add src/auth/oauth.ts src/auth/oauth.test.ts
|
|
git commit -S \
|
|
-m "feat(auth): add OAuth2 refresh token support" \
|
|
-m "Implements automatic token refresh when access token expires." \
|
|
--trailer "X-Lerian-Ref: 0x1"
|
|
|
|
# Commit 3: Documentation last
|
|
git add docs/auth/oauth-setup.md README.md
|
|
git commit -S \
|
|
-m "docs: update OAuth2 setup guide" \
|
|
--trailer "X-Lerian-Ref: 0x1"
|
|
```
|
|
|
|
## Trailer Query Commands
|
|
|
|
Trailers can be queried programmatically:
|
|
|
|
**Note:** `git log --grep` searches commit message content only, not trailers. Use `--format` with `%(trailers)` to query trailer values.
|
|
|
|
```bash
|
|
# Find all commits with specific X-Lerian-Ref trailer value
|
|
git log --all --format="%H %s %(trailers:key=X-Lerian-Ref,valueonly)" | grep "0x1"
|
|
|
|
# Show all trailers for a commit
|
|
git log -1 --format="%(trailers)"
|
|
|
|
# Filter commits by trailer existence (any value)
|
|
git log --all --format="%H %s" | while read hash msg; do
|
|
git log -1 --format="%(trailers:key=X-Lerian-Ref)" $hash | grep -q "." && echo "$hash $msg"
|
|
done
|
|
```
|
|
|
|
## Important Notes
|
|
|
|
1. **Smart grouping** - Analyzes changes and proposes atomic commits for clean history
|
|
2. **GPG signing** - All commits are signed with `-S` flag (requires GPG key configured)
|
|
3. **No visible markers** - The message body stays clean and professional
|
|
4. **Trailers are standard** - Git trailers are a recognized convention (like Signed-off-by)
|
|
5. **Machine-readable** - Easy to filter/query commits with internal system reference
|
|
6. **Transparent** - System tracing is documented, just not prominently displayed
|
|
7. **Do not use --no-verify** - Always run pre-commit hooks unless user explicitly requests
|
|
8. **User confirmation** - Always present commit plan before executing
|
|
|
|
## Anti-Patterns (NEVER DO THIS)
|
|
|
|
**⛔ THESE PATTERNS ARE FORBIDDEN. DO NOT USE THEM. ⛔**
|
|
|
|
```bash
|
|
# ❌ WRONG - emoji or hashtags in message body
|
|
git commit -m "feat: add feature
|
|
|
|
🤖 Generated with [Claude Code](https://claude.com/claude-code)"
|
|
|
|
# ❌ WRONG - hashtags in message body
|
|
git commit -m "feat: add feature #ai-generated #automated"
|
|
|
|
# ❌ WRONG - Co-Authored-By in message body
|
|
git commit -m "feat: add feature
|
|
|
|
Co-Authored-By: System <noreply@example.com>"
|
|
|
|
# ❌ WRONG - HEREDOC with markers in message body
|
|
git commit -m "$(cat <<'EOF'
|
|
feat: add feature
|
|
|
|
🤖 Generated with AI
|
|
EOF
|
|
)"
|
|
|
|
# ❌ WRONG - Trailer text inside -m parameter
|
|
git commit -m "feat: add feature
|
|
|
|
X-Lerian-Ref: 0x1"
|
|
|
|
# ❌ WRONG - System reference as hashtag in message body
|
|
git commit -m "feat: add feature #0x1"
|
|
|
|
# ❌ WRONG - ANY attempt to include trailers, hashtags, or system markers in message body
|
|
# The message body (-m parameter) must ONLY contain the commit description
|
|
# NO trailers, NO signatures, NO emoji, NO hashtags, NO system markers of any kind
|
|
```
|
|
|
|
**Why these are wrong:** They put visible markers in the commit message body, making them visible in `git log --oneline` and polluting the commit history.
|
|
|
|
```bash
|
|
# ✅ CORRECT - signed commit with trailer via --trailer parameter
|
|
git commit -S \
|
|
-m "feat: add feature" \
|
|
--trailer "X-Lerian-Ref: 0x1"
|
|
```
|
|
|
|
**Why this is correct:** Trailers are separate from the message body and only visible in `git log --format=full` or `git log --format="%(trailers)"`. The commit message stays completely clean. The `-S` flag signs the commit with GPG.
|
|
|
|
## Anti-Rationalization Table
|
|
|
|
| Rationalization | Why It's WRONG | Required Action |
|
|
|-----------------|----------------|-----------------|
|
|
| "I'll commit everything at once" | Mixed changes = messy history, hard to bisect/revert. | **Analyze and group changes first** |
|
|
| "Grouping takes too long" | Clean history saves hours of debugging later. | **Always propose commit plan** |
|
|
| "I'll skip GPG signing" | Unsigned commits can't be verified. | **Use `-S` flag (skip only if no GPG key)** |
|
|
| "I'll put the trailer text in the message body" | `--trailer` is a GIT FLAG, not text. Text in `-m` is NOT a trailer. | **Use `--trailer "X-Lerian-Ref: 0x1"` as separate argument** |
|
|
| "The trailers need to be in the commit message" | NO. Trailers go via `--trailer` flag OUTSIDE the `-m` quotes. | **Structure: `git commit -S -m "msg" --trailer "X-Lerian-Ref: 0x1"` ** |
|
|
| "I'll format it nicely in the message body" | That's NOT a trailer - that's polluting the message body. | **NEVER put "X-Lerian-Ref" text inside `-m` quotes** |
|
|
| "HEREDOC will format the trailers correctly" | HEREDOC puts everything in the message body. That's WRONG. | **Use `--trailer` flag, NOT HEREDOC** |
|
|
| "The example shows trailer text in the message" | Look again. `--trailer` is OUTSIDE the `-m "..."` quotes. | **Copy the structure exactly: `-S -m "msg" --trailer "X-Lerian-Ref: 0x1"` ** |
|
|
| "I'll add a hashtag #0x1 for tracking" | Hashtags pollute the message body. Use --trailer instead. | **NEVER use hashtags. Use `--trailer "X-Lerian-Ref: 0x1"`** |
|
|
|
|
## When User Provides Message
|
|
|
|
If the user provides a commit message as argument:
|
|
1. **Single commit mode** - Skip grouping analysis, use provided message
|
|
2. Use their message as the subject/body
|
|
3. Ensure proper formatting (50 char subject, etc.)
|
|
4. Create signed commit with trailer
|
|
|
|
```bash
|
|
# User says: /ring:commit "fix login bug"
|
|
git commit -S \
|
|
-m "fix: fix login bug" \
|
|
--trailer "X-Lerian-Ref: 0x1"
|
|
```
|