[GH-ISSUE #313] AI reformatting changes attributed to human when inter_commit_move feature flag is set to false #113

Open
opened 2026-03-02 04:11:54 +03:00 by kerem · 0 comments
Owner

Originally created by @svarlamov on GitHub (Dec 29, 2025).
Original GitHub issue: https://github.com/git-ai-project/git-ai/issues/313

See the AI diff below. All changes were in fact made by Claude, but since most of the changes are correctly detected as not substantive, the checkpoint doesn't set the attribution to claude. This behavior is technically correct (not updating attribution on pure formatting changes), but when the inter_commit_move feature flag is set to false, this leads to the changes being attributed to human. When inter_commit_move is enabled, the changes correctly retain the attribution of the original substantive author.

When inter_commit_move is disabled, any of the following could work:

  • Asynchronously re-run checkpoints and/or clean up these kinds of problems after the initial checkpoint is run. A single blame run after an initial checkpoint would be easy and only needs to be done once. This could also be implemented in such a way that the blame is loaded async, but to avoid potential contention with concurrent working log ops, the cached blame would only be picked up and processed the next time that the working log is loaded or a checkpoint is run. This would get us close to perfect by the time a post commit realistically comes around.
  • Define an algorithm for attributing these changes to the AI that made them, if the formatting change is the first change in the current working log to the given line. This isn't 100% correct, but it's probably closer to expected behavior when the prior blame isn't available for performance reasons.
diff --git a/src/commands/share_tui.rs b/src/commands/share_tui.rs
index 50b24c7..7807d19 100644
--- a/src/commands/share_tui.rs
+++ b/src/commands/share_tui.rs
@@ -52,50 +52,53 @@ impl ShareConfig {
 }
 
 pub fn run_tui() -> Result<(), GitAiError> {
-    // Step 1: Use prompt_picker to select a prompt
     let repo = find_repository(&Vec::<String>::new()).ok();
-    let selected_prompt = prompt_picker::pick_prompt(repo.as_ref(), "Select Prompt to Share")?;
 
-    let selected_prompt = match selected_prompt {
-        Some(p) => p,
-        None => return Ok(()), // User cancelled
-    };
+    loop {  🤖claude
+        // Step 1: Use prompt_picker to select a prompt  🤖claude
+        let selected_prompt = prompt_picker::pick_prompt(repo.as_ref(), "Select Prompt to Share")?;  🤖claude
 
-    // Step 2: Show share configuration screen
-    let config = show_share_config_screen(&selected_prompt)?;
+        let selected_prompt = match selected_prompt {  🤖claude
+            Some(p) => p,  🤖claude
+            None => return Ok(()), // User cancelled from picker  🤖claude
+        };  🤖claude
 
-    let config = match config {
-        Some(c) => c,
-        None => {
-            // User went back - could re-launch picker, but for now just exit
-            return Ok(());
-        }
-    };
+        // Step 2: Show share configuration screen  👤Sasha Varlamov
+        let config = show_share_config_screen(&selected_prompt)?;  👤Sasha Varlamov
+  🤖claude
+        let config = match config {  👤Sasha Varlamov
+            Some(c) => c,  👤Sasha Varlamov
+            None => {  👤Sasha Varlamov
+                // User went back - re-launch picker  🤖claude
+                continue;  🤖claude
+            }  🤖claude
+        };  🤖claude
 
-    // Step 3: Create and submit bundle
-    let include_all_in_commit = config.scope_selection == ShareScope::AllInCommit;
+        // Step 3: Create and submit bundle  🤖claude
+        let include_all_in_commit = config.scope_selection == ShareScope::AllInCommit;  🤖claude
 
-    // Validate "All in PR" not implemented
-    if config.scope_selection == ShareScope::AllInPR {
-        eprintln!("Error: PR bundles are not yet implemented");
-        std::process::exit(1);
-    }
+        // Validate "All in PR" not implemented  👤Sasha Varlamov
+        if config.scope_selection == ShareScope::AllInPR {  👤Sasha Varlamov
+            eprintln!("Error: PR bundles are not yet implemented");  🤖claude
+            std::process::exit(1);  🤖claude
+        }
 
-    let prompt_record = selected_prompt.to_prompt_record();
+        let prompt_record = selected_prompt.to_prompt_record();  👤Sasha Varlamov
 
-    let response = crate::commands::share::create_bundle(
-        selected_prompt.id,
-        prompt_record,
-        config.title,
-        include_all_in_commit,
-    )?;
+        let response = crate::commands::share::create_bundle(  👤Sasha Varlamov
+            selected_prompt.id,  👤Sasha Varlamov
+            prompt_record,  👤Sasha Varlamov
+            config.title,  👤Sasha Varlamov
+            include_all_in_commit,  👤Sasha Varlamov
+        )?;  👤Sasha Varlamov
 
-    // Display result
-    println!("Bundle created successfully!");
-    println!("ID: {}", response.id);
-    println!("URL: {}", response.url);
+        // Display result  👤Sasha Varlamov
+        println!("Bundle created successfully!");  👤Sasha Varlamov
+        println!("ID: {}", response.id);  👤Sasha Varlamov
+        println!("URL: {}", response.url);  👤Sasha Varlamov
 
-    Ok(())
+        return Ok(());  🤖claude
+    }  🤖claude
 }
Originally created by @svarlamov on GitHub (Dec 29, 2025). Original GitHub issue: https://github.com/git-ai-project/git-ai/issues/313 See the AI diff below. All changes were in fact made by Claude, but since most of the changes are correctly detected as not substantive, the checkpoint doesn't set the attribution to claude. This behavior is technically correct (not updating attribution on pure formatting changes), but when the `inter_commit_move` feature flag is set to false, this leads to the changes being attributed to human. When `inter_commit_move` is enabled, the changes correctly retain the attribution of the original substantive author. When `inter_commit_move` is disabled, any of the following could work: * Asynchronously re-run checkpoints and/or clean up these kinds of problems after the initial checkpoint is run. A single blame run after an initial checkpoint would be easy and only needs to be done once. This could also be implemented in such a way that the blame is loaded async, but to avoid potential contention with concurrent working log ops, the cached blame would only be picked up and processed the next time that the working log is loaded or a checkpoint is run. This would get us close to perfect by the time a post commit realistically comes around. * * Define an algorithm for attributing these changes to the AI that made them, if the formatting change is the first change in the current working log to the given line. This isn't 100% correct, but it's probably closer to expected behavior when the prior blame isn't available for performance reasons. ```bash diff --git a/src/commands/share_tui.rs b/src/commands/share_tui.rs index 50b24c7..7807d19 100644 --- a/src/commands/share_tui.rs +++ b/src/commands/share_tui.rs @@ -52,50 +52,53 @@ impl ShareConfig { } pub fn run_tui() -> Result<(), GitAiError> { - // Step 1: Use prompt_picker to select a prompt let repo = find_repository(&Vec::<String>::new()).ok(); - let selected_prompt = prompt_picker::pick_prompt(repo.as_ref(), "Select Prompt to Share")?; - let selected_prompt = match selected_prompt { - Some(p) => p, - None => return Ok(()), // User cancelled - }; + loop { 🤖claude + // Step 1: Use prompt_picker to select a prompt 🤖claude + let selected_prompt = prompt_picker::pick_prompt(repo.as_ref(), "Select Prompt to Share")?; 🤖claude - // Step 2: Show share configuration screen - let config = show_share_config_screen(&selected_prompt)?; + let selected_prompt = match selected_prompt { 🤖claude + Some(p) => p, 🤖claude + None => return Ok(()), // User cancelled from picker 🤖claude + }; 🤖claude - let config = match config { - Some(c) => c, - None => { - // User went back - could re-launch picker, but for now just exit - return Ok(()); - } - }; + // Step 2: Show share configuration screen 👤Sasha Varlamov + let config = show_share_config_screen(&selected_prompt)?; 👤Sasha Varlamov + 🤖claude + let config = match config { 👤Sasha Varlamov + Some(c) => c, 👤Sasha Varlamov + None => { 👤Sasha Varlamov + // User went back - re-launch picker 🤖claude + continue; 🤖claude + } 🤖claude + }; 🤖claude - // Step 3: Create and submit bundle - let include_all_in_commit = config.scope_selection == ShareScope::AllInCommit; + // Step 3: Create and submit bundle 🤖claude + let include_all_in_commit = config.scope_selection == ShareScope::AllInCommit; 🤖claude - // Validate "All in PR" not implemented - if config.scope_selection == ShareScope::AllInPR { - eprintln!("Error: PR bundles are not yet implemented"); - std::process::exit(1); - } + // Validate "All in PR" not implemented 👤Sasha Varlamov + if config.scope_selection == ShareScope::AllInPR { 👤Sasha Varlamov + eprintln!("Error: PR bundles are not yet implemented"); 🤖claude + std::process::exit(1); 🤖claude + } - let prompt_record = selected_prompt.to_prompt_record(); + let prompt_record = selected_prompt.to_prompt_record(); 👤Sasha Varlamov - let response = crate::commands::share::create_bundle( - selected_prompt.id, - prompt_record, - config.title, - include_all_in_commit, - )?; + let response = crate::commands::share::create_bundle( 👤Sasha Varlamov + selected_prompt.id, 👤Sasha Varlamov + prompt_record, 👤Sasha Varlamov + config.title, 👤Sasha Varlamov + include_all_in_commit, 👤Sasha Varlamov + )?; 👤Sasha Varlamov - // Display result - println!("Bundle created successfully!"); - println!("ID: {}", response.id); - println!("URL: {}", response.url); + // Display result 👤Sasha Varlamov + println!("Bundle created successfully!"); 👤Sasha Varlamov + println!("ID: {}", response.id); 👤Sasha Varlamov + println!("URL: {}", response.url); 👤Sasha Varlamov - Ok(()) + return Ok(()); 🤖claude + } 🤖claude } ```
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/git-ai#113
No description provided.