Skip to content

Commit 05d26bc

Browse files
committed
✨ Add automatic commit style detection for default mode
Introduce local style detection that analyzes recent git history to automatically mirror the repository's commit format (gitmoji, conventional commits, or plain) when no explicit style is configured. Key changes: - Add gitmoji_override field to Config to track explicit CLI overrides - Skip style injection in default mode when no override is set - Update commit.toml prompt with style detection instructions - Agent now calls git_log to detect format patterns rather than defaulting to a specific style This ensures Git-Iris respects each project's established conventions while still producing high-quality, descriptive commit messages.
1 parent cd12f2b commit 05d26bc

File tree

5 files changed

+76
-14
lines changed

5 files changed

+76
-14
lines changed

src/agents/capabilities/commit.toml

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,12 @@ Do not skip this step.
2121
2222
## Workflow — Progressive Analysis
2323
1. **FIRST**: Call `project_docs(doc_type="context")` — understand the project's conventions
24-
2. Call `git_diff()` to get the **summary** (file list with relevance scores, no diffs yet)
25-
3. Review the summary to identify important files (highest relevance scores)
26-
4. Call `git_diff(detail="standard", files=["important-file1.rs", "important-file2.rs"])` for full diffs of key files
27-
5. Repeat step 4 for additional files if needed (stay focused on top 5-7 files max)
28-
6. Generate the commit message based on your progressive analysis
24+
2. **SECOND** (if no STYLE INSTRUCTIONS below): Call `git_log(count=10)` to detect commit format (see "Local Style Detection" section)
25+
3. Call `git_diff()` to get the **summary** (file list with relevance scores, no diffs yet)
26+
4. Review the summary to identify important files (highest relevance scores)
27+
5. Call `git_diff(detail="standard", files=["important-file1.rs", "important-file2.rs"])` for full diffs of key files
28+
6. Repeat step 5 for additional files if needed (stay focused on top 5-7 files max)
29+
7. Generate the commit message based on your progressive analysis, using the detected format
2930
3031
**CRITICAL**: Never request all diffs at once for large changesets. Always start with summary, then selectively drill into important files.
3132
@@ -62,6 +63,49 @@ When the context indicates **amend mode** (you'll see `"mode": "amend"` with an
6263
## Style Adaptation
6364
If STYLE INSTRUCTIONS are provided below, **prioritize that style** in your word choice, tone, and descriptions. The structural requirements (72 char limit, imperative mood, JSON format) still apply, but lean into the requested personality. A cosmic preset means cosmic language. A playful preset means playful vibes. Express the style!
6465
66+
## Local Style Detection (Default Mode)
67+
If NO "STYLE INSTRUCTIONS" or "GITMOJI INSTRUCTIONS" section appears below, you MUST detect and mirror the repository's commit **format**:
68+
69+
1. Call `git_log(count=10)` to analyze recent commits
70+
2. **Observe the actual patterns** — look for:
71+
- Prefix patterns (type:, [TAG], (scope), MODULE:, etc.)
72+
- Emoji usage (leading emoji, no emoji, emoji elsewhere)
73+
- Scope/ticket conventions (feat(api):, [JIRA-123], #123, etc.)
74+
- Capitalization style (lowercase, Sentence case, UPPERCASE)
75+
- Any other consistent formatting the team uses
76+
77+
3. **Common formats for reference:**
78+
79+
**Conventional Commits** — `type(scope): message`
80+
- `feat: add user authentication`
81+
- `fix(api): resolve null pointer`
82+
→ Set `emoji` to `null`. NO EMOJIS.
83+
84+
**Gitmoji** — emoji prefix
85+
- `✨ Add user authentication`
86+
- `🐛 Fix null pointer`
87+
→ Set `emoji` field appropriately.
88+
89+
**Ticket/Issue prefixes** — `[TAG-123] message` or `TAG-123: message`
90+
- `[ENG-1234] Add user authentication`
91+
- `PROJ-456: Fix null pointer`
92+
→ Mirror the exact bracket/format style. Set `emoji` to `null` unless repo mixes with emoji.
93+
94+
**Custom patterns** — mirror whatever you see
95+
- `(auth) Add user authentication` → use `(scope) message` format
96+
- `AUTH: Add user login` → use `MODULE: message` format
97+
- `[feature] Add auth` → use `[type] message` format
98+
99+
4. **CRITICAL rules:**
100+
- If NO emojis in recent commits → set `emoji` to `null`, don't add any
101+
- If conventional commits detected → use type prefix, NO emojis
102+
- Mirror the EXACT prefix style (brackets, parens, colons, spacing)
103+
- Match capitalization patterns
104+
105+
**Mirror format, NOT quality.** Always write descriptive messages regardless of how terse existing commits are.
106+
107+
**This detection is MANDATORY when no style instructions appear below.**
108+
65109
## JSON Output
66110
Return a `GeneratedMessage` with:
67111
- `emoji` (string or null)

src/agents/iris.rs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -627,10 +627,17 @@ Guidelines:
627627

628628
let preset_name = config.get_effective_preset_name();
629629
let is_conventional = preset_name == "conventional";
630-
let gitmoji_enabled = config.use_gitmoji && !is_conventional;
630+
let is_default_mode = preset_name == "default" || preset_name.is_empty();
631631

632-
// Inject instruction preset if configured
633-
if !preset_name.is_empty() && preset_name != "default" {
632+
// For commits in default mode with no explicit gitmoji override, use style detection
633+
// (don't inject any style instructions - let the agent detect from git_log)
634+
let use_style_detection =
635+
capability == "commit" && is_default_mode && config.gitmoji_override.is_none();
636+
637+
let gitmoji_enabled = config.use_gitmoji && !is_conventional && !use_style_detection;
638+
639+
// Inject instruction preset if configured (skip for default mode)
640+
if !preset_name.is_empty() && !is_default_mode {
634641
let library = crate::instruction_presets::get_instruction_preset_library();
635642
if let Some(preset) = library.get_preset(preset_name) {
636643
tracing::info!("📋 Injecting '{}' preset style instructions", preset_name);
@@ -644,7 +651,11 @@ Guidelines:
644651

645652
// Handle commit-specific styling (structured JSON output with emoji field)
646653
if capability == "commit" {
647-
if gitmoji_enabled {
654+
if use_style_detection {
655+
// In default mode, let the agent detect style from git_log
656+
// The commit.toml prompt has instructions for this
657+
tracing::info!("🔍 Using local commit style detection (default mode)");
658+
} else if gitmoji_enabled {
648659
system_prompt.push_str("\n\n=== GITMOJI INSTRUCTIONS ===\n");
649660
system_prompt.push_str("Set the 'emoji' field to a single relevant gitmoji. ");
650661
system_prompt.push_str(

src/commands.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,7 @@ pub fn handle_project_config_command(
317317
temp_instructions: None,
318318
temp_preset: None,
319319
is_project_config: true,
320+
gitmoji_override: None,
320321
});
321322

322323
let mut changes_made = false;

src/common.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -92,11 +92,13 @@ impl CommonParams {
9292
config.set_temp_preset(Some(preset.clone()));
9393
}
9494

95-
if let Some(use_gitmoji) = self.resolved_gitmoji()
96-
&& config.use_gitmoji != use_gitmoji
97-
{
98-
config.use_gitmoji = use_gitmoji;
99-
changes_made = true;
95+
// Track whether gitmoji was explicitly set via CLI (for style detection)
96+
if let Some(use_gitmoji) = self.resolved_gitmoji() {
97+
config.gitmoji_override = Some(use_gitmoji);
98+
if config.use_gitmoji != use_gitmoji {
99+
config.use_gitmoji = use_gitmoji;
100+
changes_made = true;
101+
}
100102
}
101103

102104
Ok(changes_made)

src/config.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ pub struct Config {
5151
/// Runtime-only: flag if loaded from project config
5252
#[serde(skip)]
5353
pub is_project_config: bool,
54+
/// Runtime-only: whether gitmoji was explicitly set via CLI (None = use style detection)
55+
#[serde(skip)]
56+
pub gitmoji_override: Option<bool>,
5457
}
5558

5659
fn default_true() -> bool {
@@ -86,6 +89,7 @@ impl Default for Config {
8689
temp_instructions: None,
8790
temp_preset: None,
8891
is_project_config: false,
92+
gitmoji_override: None,
8993
}
9094
}
9195
}

0 commit comments

Comments
 (0)