From 81fd65b14ddb70c2e606f8aefa1c60b2c30fcbb7 Mon Sep 17 00:00:00 2001 From: Greg Gauthier Date: Tue, 3 Mar 2026 20:44:39 +0000 Subject: [PATCH] refactor(cmd): remove automatic .bak backup creation Eliminate .bak file backups from edit, docs, lint, testgen, and agent commands to simplify safety features, relying on previews and confirmations instead. Update README, architecture docs, troubleshooting, and TODOs to reflect changes. Adjust tests to remove backup assertions. --- README.md | 6 +----- cmd/agent.go | 5 +---- cmd/docs.go | 11 ----------- cmd/edit.go | 18 ++++-------------- cmd/lint.go | 15 ++------------- cmd/run_test.go | 7 ------- cmd/testgen.go | 17 +---------------- docs/ARCHITECTURE.md | 6 +----- docs/TROUBLESHOOTING.md | 4 ++-- todo/queued/interactive-agent.md | 2 +- 10 files changed, 13 insertions(+), 78 deletions(-) diff --git a/README.md b/README.md index 2f23a41..cfa09da 100644 --- a/README.md +++ b/README.md @@ -89,7 +89,6 @@ grokkit edit utils.go "add detailed docstrings to all exported functions" ``` **Safety features:** -- Creates `.bak` backup before any changes - Shows preview with diff-style output - Requires confirmation before applying - Uses silent streaming (no console spam) @@ -189,7 +188,6 @@ grokkit docs app.py -m grok-4 | Shell | Shell comments (`# function: desc, # Args: ...`) | **Safety features:** -- Creates `.bak` backup before any changes - Shows first 50 lines of documented code as preview - Requires confirmation (unless `--auto-apply`) @@ -202,7 +200,7 @@ grokkit docs app.py -m grok-4 - Python: Pytest with `@parametrize`. - C: Check framework suites. - C++: Google Test `EXPECT_*`. -- Boosts coverage; safe preview/backup. +- Boosts coverage; safe preview. **CLI examples**: ```bash @@ -213,7 +211,6 @@ grokkit testgen foo.c bar.cpp **Safety features**: - Lang detection via `internal/linter`. -- Creates `test_*.bak` backups. - Unified diff preview. - Y/N (--yes auto). @@ -253,7 +250,6 @@ grokkit lint script.rb -m grok-4 - **Shell** (shellcheck) **Safety features:** -- Creates `.bak` backup before changes - Shows preview of fixes - Verifies fixes by re-running linter - Requires confirmation (unless `--auto-fix`) diff --git a/cmd/agent.go b/cmd/agent.go index 0d91304..def2a61 100644 --- a/cmd/agent.go +++ b/cmd/agent.go @@ -79,9 +79,6 @@ var agentCmd = &cobra.Command{ continue } - backupPath := file + ".bak" - _ = os.WriteFile(backupPath, original, 0644) - messages := []map[string]string{ {"role": "system", "content": "You are an expert programmer. Remove all unnecessary comments including last modified timestamps and ownership comments. Return clean, complete file content with no explanations, markdown, diffs, or extra text."}, {"role": "user", "content": fmt.Sprintf("File: %s\n\nOriginal content:\n%s\n\nTask: %s", filepath.Base(file), original, instruction)}, @@ -107,7 +104,7 @@ var agentCmd = &cobra.Command{ if answer == "a" { applyAll = true } else if answer != "y" { - color.Yellow("Skipped %s (backup kept)", file) + color.Yellow("Skipped %s", file) continue } } diff --git a/cmd/docs.go b/cmd/docs.go index cc253e1..466b857 100644 --- a/cmd/docs.go +++ b/cmd/docs.go @@ -32,7 +32,6 @@ Supported doc styles: Shell Shell comments (# function: ...) Safety features: -- Creates .bak backup before modifying files - Shows preview of changes before applying - Requires confirmation unless --auto-apply is used`, Args: cobra.MinimumNArgs(1), @@ -124,15 +123,6 @@ func processDocsFile(client grok.AIClient, model, filePath string) { } } - // Create backup - backupPath := filePath + ".bak" - if err := os.WriteFile(backupPath, originalContent, 0644); err != nil { - logger.Error("failed to create backup", "file", filePath, "error", err) - color.Red("❌ Failed to create backup: %v", err) - return - } - logger.Info("backup created", "backup", backupPath) - if err := os.WriteFile(filePath, []byte(documented), 0644); err != nil { logger.Error("failed to write documented file", "file", filePath, "error", err) color.Red("❌ Failed to write file: %v", err) @@ -141,7 +131,6 @@ func processDocsFile(client grok.AIClient, model, filePath string) { logger.Info("documentation applied successfully", "file", filePath) color.Green("βœ… Documentation applied: %s", filePath) - color.Cyan("πŸ’Ύ Original saved to: %s", backupPath) } func buildDocsMessages(language, code string) []map[string]string { diff --git a/cmd/edit.go b/cmd/edit.go index 2df21d1..b8ae8d8 100644 --- a/cmd/edit.go +++ b/cmd/edit.go @@ -15,7 +15,7 @@ import ( var editCmd = &cobra.Command{ Use: "edit FILE INSTRUCTION", - Short: "Edit a file in-place with Grok (safe preview + backup)", + Short: "Edit a file in-place with Grok (safe preview)", Args: cobra.ExactArgs(2), Run: func(cmd *cobra.Command, args []string) { filePath := args[0] @@ -44,15 +44,6 @@ var editCmd = &cobra.Command{ logger.Debug("file read successfully", "file", filePath, "size_bytes", len(original)) cleanedOriginal := removeLastModifiedComments(string(original)) - backupPath := filePath + ".bak" - logger.Debug("creating backup", "backup_path", backupPath) - if err := os.WriteFile(backupPath, original, 0644); err != nil { - logger.Error("failed to create backup", "backup_path", backupPath, "error", err) - color.Red("Failed to create backup: %v", err) - os.Exit(1) - } - logger.Info("backup created", "backup_path", backupPath) - client := grok.NewClient() messages := []map[string]string{ {"role": "system", "content": "You are an expert programmer. Remove all unnecessary comments including last modified timestamps and ownership comments. Return only the cleaned code with no explanations, no markdown, no extra text."}, @@ -73,11 +64,11 @@ var editCmd = &cobra.Command{ var confirm string if _, err := fmt.Scanln(&confirm); err != nil { color.Red("Failed to read input: %v", err) - color.Yellow("Changes discarded. Backup saved as %s", backupPath) + color.Yellow("Changes discarded.") return } if confirm != "y" && confirm != "Y" { - color.Yellow("Changes discarded. Backup saved as %s", backupPath) + color.Yellow("Changes discarded.") return } @@ -89,10 +80,9 @@ var editCmd = &cobra.Command{ } logger.Info("changes applied successfully", "file", filePath, - "backup", backupPath, "original_size", len(original), "new_size", len(newContent)) - color.Green("βœ… Applied successfully! Backup: %s", backupPath) + color.Green("βœ… Applied successfully!") }, } diff --git a/cmd/lint.go b/cmd/lint.go index 47a4baf..8b70dd7 100644 --- a/cmd/lint.go +++ b/cmd/lint.go @@ -132,16 +132,6 @@ func runLint(cmd *cobra.Command, args []string) { fixedCode := grok.CleanCodeResponse(response) logger.Info("received AI fixes", "file", absPath, "fixed_size", len(fixedCode)) - // Create backup - backupPath := absPath + ".bak" - if err := os.WriteFile(backupPath, originalContent, 0644); err != nil { - logger.Error("failed to create backup", "file", absPath, "error", err) - color.Red("❌ Failed to create backup: %v", err) - return - } - logger.Info("backup created", "backup", backupPath) - color.Green("πŸ’Ύ Backup created: %s", backupPath) - // Show preview if not auto-fix if !autoFix { fmt.Println() @@ -167,14 +157,14 @@ func runLint(cmd *cobra.Command, args []string) { var response string if _, err := fmt.Scanln(&response); err != nil { logger.Info("failed to read user input", "file", absPath, "error", err) - color.Yellow("❌ Cancelled. Backup preserved at: %s", backupPath) + color.Yellow("❌ Cancelled. No changes made.") return } response = strings.ToLower(strings.TrimSpace(response)) if response != "y" && response != "yes" { logger.Info("user cancelled fix application", "file", absPath) - color.Yellow("❌ Cancelled. Backup preserved at: %s", backupPath) + color.Yellow("❌ Cancelled. No changes made.") return } } @@ -188,7 +178,6 @@ func runLint(cmd *cobra.Command, args []string) { logger.Info("fixes applied successfully", "file", absPath) color.Green("βœ… Fixes applied successfully!") - color.Cyan("πŸ’Ύ Original saved to: %s", backupPath) // Optionally run linter again to verify color.Cyan("\nπŸ” Re-running linter to verify fixes...") diff --git a/cmd/run_test.go b/cmd/run_test.go index 6f700bb..770d170 100644 --- a/cmd/run_test.go +++ b/cmd/run_test.go @@ -386,7 +386,6 @@ func TestProcessDocsFilePreviewAndCancel(t *testing.T) { t.Fatal(err) } defer func() { _ = os.Remove(f.Name()) }() - defer func() { _ = os.Remove(f.Name() + ".bak") }() mock := &mockStreamer{response: "package main\n\n// Foo does nothing.\nfunc Foo() {}\n"} @@ -426,7 +425,6 @@ func TestProcessDocsFileAutoApply(t *testing.T) { t.Fatal(err) } defer func() { _ = os.Remove(f.Name()) }() - defer func() { _ = os.Remove(f.Name() + ".bak") }() // CleanCodeResponse will trim the trailing newline from the AI response. aiResponse := "package main\n\n// Bar does nothing.\nfunc Bar() {}\n" @@ -447,11 +445,6 @@ func TestProcessDocsFileAutoApply(t *testing.T) { if string(content) != documented { t.Errorf("file content = %q, want %q", string(content), documented) } - // Verify backup was created with original content. - backup, _ := os.ReadFile(f.Name() + ".bak") - if string(backup) != original { - t.Errorf("backup content = %q, want %q", string(backup), original) - } } func TestRunDocs(t *testing.T) { diff --git a/cmd/testgen.go b/cmd/testgen.go index 8f7414d..c8cb74d 100644 --- a/cmd/testgen.go +++ b/cmd/testgen.go @@ -92,7 +92,6 @@ func processTestgenFile(client *grok.Client, filePath, lang, systemPrompt, model testPath := getTestFilePath(filePath, lang) // Handle existing test file - var origTest []byte testExists := true testInfo, err := os.Stat(testPath) if os.IsNotExist(err) { @@ -101,20 +100,6 @@ func processTestgenFile(client *grok.Client, filePath, lang, systemPrompt, model return fmt.Errorf("stat test file: %w", err) } else if testInfo.IsDir() { return fmt.Errorf("test path is dir: %s", testPath) - } else { - origTest, err = os.ReadFile(testPath) - if err != nil { - return fmt.Errorf("read existing test: %w", err) - } - } - - // Backup existing test - backupPath := testPath + ".bak" - if testExists { - if err := os.WriteFile(backupPath, origTest, 0644); err != nil { - return fmt.Errorf("backup test file: %w", err) - } - color.Yellow("πŸ’Ύ Backup: %s", backupPath) } // Generate tests @@ -167,7 +152,7 @@ func processTestgenFile(client *grok.Client, filePath, lang, systemPrompt, model } confirm = strings.TrimSpace(strings.ToLower(confirm)) if confirm != "y" && confirm != "yes" { - color.Yellow("⏭️ Skipped %s (backup: %s)", testPath, backupPath) + color.Yellow("⏭️ Skipped %s", testPath) return nil } } diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 945a3ba..c269669 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -334,7 +334,6 @@ User: grokkit edit file.go "instruction" editCmd.Run() β”œβ”€β†’ Validate file exists β”œβ”€β†’ Read original content - β”œβ”€β†’ Create backup (.bak) β”œβ”€β†’ Clean "Last modified" comments ↓ grok.Client.StreamSilent() # Get AI response @@ -347,8 +346,7 @@ Display preview # Show diff-style output Prompt user (y/n) ↓ Write file (if confirmed) - β”œβ”€β†’ logger.Info() # Log changes - └─→ Keep backup + └─→ logger.Info() # Log changes ``` ### Commit Command Flow @@ -394,8 +392,6 @@ grok.Client.StreamSilent() # Get fixed code ↓ grok.CleanCodeResponse() # Remove markdown ↓ -Create backup (.bak) - ↓ (if not --auto-fix) β†’ Show preview + prompt ↓ Write fixed file diff --git a/docs/TROUBLESHOOTING.md b/docs/TROUBLESHOOTING.md index 6717e35..790ec85 100644 --- a/docs/TROUBLESHOOTING.md +++ b/docs/TROUBLESHOOTING.md @@ -581,8 +581,8 @@ After applying AI fixes, re-running the linter still reports issues. **Solution:** ```bash # Some issues may require manual intervention -# Check the backup file to compare -diff file.py file.py.bak +# Use git diff to compare changes +git diff file.py # Apply fixes iteratively grokkit lint file.py # Apply fixes diff --git a/todo/queued/interactive-agent.md b/todo/queued/interactive-agent.md index 78f94d9..55db561 100644 --- a/todo/queued/interactive-agent.md +++ b/todo/queued/interactive-agent.md @@ -31,7 +31,7 @@ grokkit chat --agent # or new subcommand: grokkit agent-chat - Safe-by-default workflow: - Always preview changes (diff style, same as current `edit`/`scaffold`) - Require explicit confirmation (`y/n` or `--yes`) - - Create `.bak` backups automatically + - Preview and confirm all changes before application - Ability to chain actions naturally in conversation: - β€œThe scaffold tests are flaky on Windows paths β€” fix it and add a test case.” - β€œRefactor the context harvester to use rg, then run make test.”