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.
This commit is contained in:
parent
7881ac2446
commit
81fd65b14d
@ -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`)
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
11
cmd/docs.go
11
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 {
|
||||
|
||||
18
cmd/edit.go
18
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!")
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
15
cmd/lint.go
15
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...")
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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.”
|
||||
|
||||
Loading…
Reference in New Issue
Block a user