Commit 007f2bc

bryfry <bryon@fryer.io>
2025-09-27 23:14:34
003 issues
1 parent d5d9ffb
001_init.md
@@ -1,7 +1,7 @@
 ---
 id: 001
 title: Implement init command
-status: in-progress
+status: completed
 type: feature
 created: 2025-09-24
 ---
@@ -75,22 +75,8 @@ Implement the `tissue init` command to initialize issue tracking in a git reposi
 
 ## Technical Notes
 
-### Orphan Branch Creation
-```go
-orphanRef := plumbing.NewSymbolicReference(
-    plumbing.HEAD,
-    plumbing.ReferenceName("refs/heads/issues"),
-)
-repo.Storer.SetReference(orphanRef)
-```
-
-### Worktree Limitation
-go-git v5 doesn't support `git worktree add` natively. Using os/exec as temporary solution:
-```go
-// TODO: Remove dependency on git CLI when go-git supports worktrees
-// Track progress: https://github.com/go-git/go-git/pull/396
-cmd := exec.Command("git", "worktree", "add", "issues", "issues")
-```
+- go-git v5 doesn't support `git worktree add` natively - using os/exec as workaround
+- Track worktree support progress: https://github.com/go-git/go-git/pull/396
 
 ## Acceptance Criteria
 
@@ -105,46 +91,19 @@ cmd := exec.Command("git", "worktree", "add", "issues", "issues")
 ## Problems Encountered
 
 ### Problem 1: Orphan branch not truly orphan
-**Date:** 2025-09-24
-**Description:** The created "issues" branch was not truly orphan - it had parent commits and shared history with the main branch.
+**Fixed:** The created "issues" branch was not truly orphan - it had parent commits and shared history with the main branch. Solution was to clear the index and working directory before committing.
 
-**Root Cause:**
-- Setting `plumbing.NewSymbolicReference` to point HEAD to a new branch name doesn't clear the index or working directory
-- When committing without clearing the index first, the commit inherits the parent from the current HEAD
-- The working directory still contains all files from the previous branch
-
-**Expected Behavior:**
-- `git checkout --orphan issues` creates a new branch with no history
-- `git rm -rf .` clears the index and working directory
-- First commit has no parent
-
-**Fix:**
-After creating the symbolic reference, must:
-1. Clear the entire git index using `worktree.RemoveGlob("*")`
-2. Clean the working directory of all tracked files
-3. Only then add the new files (README.md, .gitignore) and commit
-
-This ensures the branch starts with zero commits and empty directory, creating truly divergent history.
-
-## Summary
-
-The `tissue init` command has been successfully implemented with most requirements:
+## Status
 
 ### Completed:
-1. ✅ Creates a truly orphan branch (no parent commits)
-2. ✅ Initializes branch with README.md and .gitignore
-3. ✅ Automatically sets up git worktree
-4. ✅ `--issues-dir` flag allows custom directory (defaults to ./issues)
-5. ✅ `--issues-branch` flag allows custom branch name (defaults to issues)
-6. ✅ Uses constants `_issuesBranchDefault` and `_issuesDirDefault` for defaults
-7. ✅ Pushes to remote if available
-8. ✅ Returns to original branch after completion
-9. ✅ Error handling follows Go style guide
-10. ✅ Clear error messages and user feedback
+- ✅ Creates a truly orphan branch (no parent commits)
+- ✅ Initializes branch with README.md and .gitignore
+- ✅ Automatically sets up git worktree
+- ✅ `--issues-dir` flag allows custom directory (defaults to ./issues)
+- ✅ `--issues-branch` flag allows custom branch name (defaults to issues)
+- ✅ Pushes to remote if available
+- ✅ Returns to original branch after completion
+- ✅ Clear error messages and user feedback
 
 ### Remaining:
-- 🔲 Use git-configured user/email for commits (currently hardcoded)
-
-## Related Issues
-
-- Future: Remove os/exec dependency when go-git adds worktree support (PR #396)
+- None - see issue #003 for git user config enhancement
002_init-remote.md
@@ -22,23 +22,6 @@ The current `tissue init` command has several issues with remote branch handling
 3. **Multiple remotes not handled**: When multiple remotes exist with the same branch name, there's no way to specify which one to use
 4. **Silent push failures**: Push failures are only logged as warnings, potentially leaving users unaware of sync issues
 
-## Current Behavior
-
-```go
-// cmd/init.go lines 210-227
-remotes, err := repo.Remotes()
-if err == nil && len(remotes) > 0 {
-    fmt.Println("Pushing to remote...")
-    refSpec := fmt.Sprintf("refs/heads/%s:refs/heads/%s", issuesBranch, issuesBranch)
-    err = repo.Push(&git.PushOptions{
-        RemoteName: "origin",  // <-- Hardcoded assumption
-        RefSpecs: []config.RefSpec{
-            config.RefSpec(refSpec),
-        },
-    })
-    // ...
-}
-```
 
 ## Edge Cases to Consider
 
@@ -73,631 +56,28 @@ if err == nil && len(remotes) > 0 {
 
 ## Proposed Solution
 
-### 1. Add `--remote` flag
-```go
-var remoteName string
-cmd.Flags().StringVar(&remoteName, "remote", "", "Remote to use for pushing the issues branch")
-```
-
-### 2. Implement remote branch detection
-```go
-func checkRemoteBranches(repo *git.Repository, branchName string) (map[string]bool, error) {
-    remoteBranches := make(map[string]bool)
-
-    remotes, err := repo.Remotes()
-    if err != nil {
-        return nil, err
-    }
-
-    for _, remote := range remotes {
-        refs, err := remote.List(&git.ListOptions{})
-        if err != nil {
-            continue // Skip unreachable remotes
-        }
-
-        for _, ref := range refs {
-            if ref.Name() == plumbing.ReferenceName("refs/heads/"+branchName) {
-                remoteBranches[remote.Config().Name] = true
-            }
-        }
-    }
-
-    return remoteBranches, nil
-}
-```
-
-### 3. Improve initialization flow
-```go
-func initRunE(cmd *cobra.Command, args []string, issuesDir, issuesBranch, remoteName string) error {
-    // ... existing validation ...
-
-    // Check remote branches
-    remotesWithBranch, err := checkRemoteBranches(repo, issuesBranch)
-    if err != nil {
-        // Log warning but continue - remotes might be temporarily unavailable
-        fmt.Printf("Warning: Could not check remote branches: %v\n", err)
-    }
-
-    remotes, _ := repo.Remotes()
-    numRemotes := len(remotes)
-
-    // Case 4: Multiple remotes, one has issues branch
-    if numRemotes > 1 && len(remotesWithBranch) == 1 {
-        for remote := range remotesWithBranch {
-            fmt.Printf("Found existing '%s' branch on remote '%s'\n", issuesBranch, remote)
-            // Track the existing remote branch
-            return checkoutAndTrackRemoteBranch(repo, remote, issuesBranch, issuesDir)
-        }
-    }
-
-    // Case 5: Multiple remotes, multiple have issues branch
-    if len(remotesWithBranch) > 1 && remoteName == "" {
-        remoteList := []string{}
-        for r := range remotesWithBranch {
-            remoteList = append(remoteList, r)
-        }
-        return fmt.Errorf("branch '%s' exists on multiple remotes: %v. Use --remote flag to specify which remote to use",
-            issuesBranch, remoteList)
-    }
-
-    // Single remote with issues branch
-    if numRemotes == 1 && len(remotesWithBranch) == 1 {
-        for remote := range remotesWithBranch {
-            fmt.Printf("Found existing '%s' branch on remote '%s'\n", issuesBranch, remote)
-            return checkoutAndTrackRemoteBranch(repo, remote, issuesBranch, issuesDir)
-        }
-    }
-
-    // No existing remote branch - create new orphan branch
-    // ... continue with branch creation ...
-
-    // Determine which remote to use for push
-    targetRemote := determineTargetRemote(repo, remoteName, numRemotes)
-
-    if numRemotes > 1 && targetRemote == "" && remoteName == "" {
-        // Case 3: Multiple remotes, no issues branch, no --remote flag
-        fmt.Println("\nMultiple remotes detected. Not pushing to any remote.")
-        fmt.Println("To push to a specific remote, run:")
-        fmt.Println("  tissue init --remote <remote-name>")
-        fmt.Println("\nOr push manually with git:")
-        fmt.Printf("  git push -u <remote-name> %s\n", issuesBranch)
-        return nil
-    }
-
-    // ... continue with push if targetRemote is set ...
-}
-
-func determineTargetRemote(repo *git.Repository, requestedRemote string, numRemotes int) string {
-    if requestedRemote != "" {
-        // Validate that requested remote exists
-        remotes, _ := repo.Remotes()
-        for _, remote := range remotes {
-            if remote.Config().Name == requestedRemote {
-                return requestedRemote
-            }
-        }
-        // Remote doesn't exist - will error later
-        return ""
-    }
-
-    if numRemotes == 0 {
-        return ""
-    }
-
-    // Case 2: Single remote (use it regardless of name)
-    if numRemotes == 1 {
-        remotes, _ := repo.Remotes()
-        return remotes[0].Config().Name
-    }
-
-    // Case 3: Multiple remotes without --remote flag
-    // Don't push automatically
-    return ""
-}
-
-func checkoutAndTrackRemoteBranch(repo *git.Repository, remoteName, branchName, issuesDir string) error {
-    // Fetch the remote branch
-    remote, err := repo.Remote(remoteName)
-    if err != nil {
-        return fmt.Errorf("getting remote %s: %w", remoteName, err)
-    }
-
-    err = remote.Fetch(&git.FetchOptions{
-        RefSpecs: []config.RefSpec{
-            config.RefSpec(fmt.Sprintf("+refs/heads/%s:refs/remotes/%s/%s", branchName, remoteName, branchName)),
-        },
-    })
-    if err != nil && err != git.NoErrAlreadyUpToDate {
-        return fmt.Errorf("fetching remote branch: %w", err)
-    }
-
-    // Create local branch tracking the remote
-    refName := plumbing.ReferenceName(fmt.Sprintf("refs/heads/%s", branchName))
-    remoteRef := plumbing.ReferenceName(fmt.Sprintf("refs/remotes/%s/%s", remoteName, branchName))
-
-    // Get the remote branch reference
-    ref, err := repo.Reference(remoteRef, true)
-    if err != nil {
-        return fmt.Errorf("getting remote branch reference: %w", err)
-    }
-
-    // Create local branch pointing to same commit
-    err = repo.Storer.SetReference(plumbing.NewHashReference(refName, ref.Hash()))
-    if err != nil {
-        return fmt.Errorf("creating local branch: %w", err)
-    }
-
-    // Set up tracking
-    cfg, err := repo.Config()
-    if err != nil {
-        return fmt.Errorf("getting repo config: %w", err)
-    }
-
-    cfg.Branches[branchName] = &config.Branch{
-        Name:   branchName,
-        Remote: remoteName,
-        Merge:  refName,
-    }
-
-    err = repo.Storer.SetConfig(cfg)
-    if err != nil {
-        return fmt.Errorf("setting branch tracking: %w", err)
-    }
-
-    // Set up worktree
-    fmt.Printf("Setting up git worktree at %s...\n", issuesDir)
-    // ... continue with worktree setup ...
-
-    return nil
-}
-```
-
-## Implementation Plan
-
-1. **Phase 1: Detection** (Priority: High)
-   - Add remote branch detection function
-   - Warn user if remote branch exists
-   - Fail gracefully with informative error
-
-2. **Phase 2: Remote Selection** (Priority: High)
-   - Add `--remote` flag
-   - Implement smart remote selection logic
-   - Update push logic to use selected remote
-
-3. **Phase 3: Conflict Resolution** (Priority: Medium)
-   - Add `--track` flag to track existing remote branch
-   - Add `--force` flag to override remote branch
-   - Implement interactive mode for conflict resolution
-
-4. **Phase 4: Better Error Handling** (Priority: Medium)
-   - Improve error messages with actionable suggestions
-   - Add `--dry-run` flag to preview actions
-   - Log all remote operations clearly
-
-## Test Scenarios
-
-### Test 1: No remotes configured
-**Setup:**
-```bash
-# Create a new local repository
-mkdir test-tissue-1
-cd test-tissue-1
-git init
-echo "# Test Repo" > README.md
-git add README.md
-git commit -m "Initial commit"
-```
-
-**Test:**
-```bash
-tissue init
-```
-
-**Expected Result:**
-- Should create orphan issues branch locally
-- Should set up worktree
-- No push attempts
-- Success message without any remote warnings
-
----
-
-### Test 2: Single remote (not named "origin")
-**Setup:**
-```bash
-# Create a bare remote repository
-mkdir -p /tmp/test-remotes/upstream.git
-cd /tmp/test-remotes/upstream.git
-git init --bare
-
-# Create local repository with non-origin remote
-mkdir test-tissue-2
-cd test-tissue-2
-git init
-echo "# Test Repo" > README.md
-git add README.md
-git commit -m "Initial commit"
-git remote add upstream /tmp/test-remotes/upstream.git
-git push -u upstream main
-```
-
-**Test:**
-```bash
-tissue init
-```
-
-**Expected Result:**
-- Should create orphan issues branch
-- Should automatically detect and use "upstream" remote
-- Should push to upstream
-- Success message showing "Pushed issues branch to remote 'upstream'"
-
----
-
-### Test 3: Multiple remotes, no issues branch
-**Setup:**
-```bash
-# Create two bare remote repositories
-mkdir -p /tmp/test-remotes/origin.git
-mkdir -p /tmp/test-remotes/upstream.git
-cd /tmp/test-remotes/origin.git
-git init --bare
-cd /tmp/test-remotes/upstream.git
-git init --bare
-
-# Create local repository with multiple remotes
-mkdir test-tissue-3
-cd test-tissue-3
-git init
-echo "# Test Repo" > README.md
-git add README.md
-git commit -m "Initial commit"
-git remote add origin /tmp/test-remotes/origin.git
-git remote add upstream /tmp/test-remotes/upstream.git
-git push -u origin main
-```
-
-**Test A (without --remote flag):**
-```bash
-tissue init
-```
-
-**Expected Result:**
-- Should create orphan issues branch locally
-- Should NOT push to any remote
-- Should display message about multiple remotes
-- Should show instructions for using --remote flag
-- Should show manual git push command
-
-**Test B (with --remote flag):**
-```bash
-tissue init --remote origin
-```
-
-**Expected Result:**
-- Should create orphan issues branch
-- Should push to specified "origin" remote
-- Success message
-
----
-
-### Test 4: Multiple remotes, one has issues branch
-**Setup:**
-```bash
-# Create two bare remotes
-mkdir -p /tmp/test-remotes/origin.git
-mkdir -p /tmp/test-remotes/upstream.git
-cd /tmp/test-remotes/origin.git
-git init --bare
-cd /tmp/test-remotes/upstream.git
-git init --bare
-
-# Create first repo and push issues branch to origin
-mkdir test-tissue-4a
-cd test-tissue-4a
-git init
-echo "# Test Repo" > README.md
-git add README.md
-git commit -m "Initial commit"
-git remote add origin /tmp/test-remotes/origin.git
-git push -u origin main
-
-# Create and push issues branch
-git checkout --orphan issues
-git rm -rf .
-echo "# Issues" > README.md
-git add README.md
-git commit -m "Initialize issues"
-git push -u origin issues
-git checkout main
-
-# Now create second repo with both remotes but issues only on origin
-cd ..
-mkdir test-tissue-4b
-cd test-tissue-4b
-git init
-echo "# Test Repo" > README.md
-git add README.md
-git commit -m "Initial commit"
-git remote add origin /tmp/test-remotes/origin.git
-git remote add upstream /tmp/test-remotes/upstream.git
-git fetch origin
-```
-
-**Test:**
-```bash
-tissue init
-```
-
-**Expected Result:**
-- Should detect issues branch on origin
-- Should display "Found existing 'issues' branch on remote 'origin'"
-- Should fetch and track the existing branch
-- Should set up worktree
-- Success message
-
----
-
-### Test 5: Multiple remotes, multiple have issues branch
-**Setup:**
-```bash
-# Create two bare remotes
-mkdir -p /tmp/test-remotes/origin.git
-mkdir -p /tmp/test-remotes/upstream.git
-cd /tmp/test-remotes/origin.git
-git init --bare
-cd /tmp/test-remotes/upstream.git
-git init --bare
-
-# Create first repo and push issues to both remotes
-mkdir test-tissue-5a
-cd test-tissue-5a
-git init
-echo "# Test Repo" > README.md
-git add README.md
-git commit -m "Initial commit"
-git remote add origin /tmp/test-remotes/origin.git
-git remote add upstream /tmp/test-remotes/upstream.git
-
-# Create and push issues branch to both
-git checkout --orphan issues
-git rm -rf .
-echo "# Issues Origin" > README.md
-git add README.md
-git commit -m "Initialize issues on origin"
-git push -u origin issues
-
-# Modify and push to upstream (different content)
-echo "# Issues Upstream" > README.md
-git add README.md
-git commit -m "Initialize issues on upstream"
-git push -u upstream issues
-git checkout main
-
-# Create second repo that will see both
-cd ..
-mkdir test-tissue-5b
-cd test-tissue-5b
-git init
-echo "# Test Repo" > README.md
-git add README.md
-git commit -m "Initial commit"
-git remote add origin /tmp/test-remotes/origin.git
-git remote add upstream /tmp/test-remotes/upstream.git
-git fetch --all
-```
-
-**Test:**
-```bash
-tissue init
-```
-
-**Expected Result:**
-- Should detect issues branch on both remotes
-- Should display error: "Branch 'issues' exists on multiple remotes: [origin, upstream]. Use --remote flag to specify which remote to use"
-- Should exit with error
-
-**Test with --remote:**
-```bash
-tissue init --remote origin
-```
-
-**Expected Result:**
-- Should track issues branch from origin
-- Success message
-
----
-
-### Test 6: Unreachable remote
-**Setup:**
-```bash
-# Create local repository with unreachable remote
-mkdir test-tissue-6
-cd test-tissue-6
-git init
-echo "# Test Repo" > README.md
-git add README.md
-git commit -m "Initial commit"
-git remote add origin ssh://nonexistent.example.com/repo.git
-```
-
-**Test:**
-```bash
-tissue init
-```
-
-**Expected Result:**
-- Should display warning about unable to check remote branches
-- Should continue with local branch creation
-- Should attempt push and show warning when it fails
-- Should still complete successfully with worktree setup
-
----
-
-### Test 7: Invalid --remote flag
-**Setup:**
-```bash
-# Create repository with one remote
-mkdir test-tissue-7
-cd test-tissue-7
-git init
-echo "# Test Repo" > README.md
-git add README.md
-git commit -m "Initial commit"
-git remote add origin /tmp/test-remotes/origin.git
-```
-
-**Test:**
-```bash
-tissue init --remote nonexistent
-```
+1. Add `--remote` flag to specify which remote to use
+2. Add `--force-local` flag to bypass remote checks
+3. Implement remote branch detection to avoid conflicts
+4. Smart remote selection:
+   - Single remote: use it automatically
+   - Multiple remotes: require --remote flag or skip push
+   - Detect and track existing remote branches
+5. Better error handling for SSH and connectivity issues
+
+## Test Cases Summary
+
+1. **No remotes**: Creates local branch, sets up worktree ✅
+2. **Single remote (not "origin")**: Auto-detects and uses it ✅
+3. **Multiple remotes, no issues branch**: Requires --remote flag or skips push ✅
+4. **Multiple remotes, one has issues**: Tracks existing branch ✅
+5. **Multiple remotes, multiple have issues**: Requires --remote flag ✅
+6. **Unreachable remote**: Shows warning, continues locally ✅
+7. **Invalid --remote flag**: Fails with clear error ✅
+8. **Local issues branch exists**: Fails with appropriate message ✅
+9. **Local branch exists, worktree missing**: Reuses branch ✅ Fixed
+10. **SSH connectivity issues**: Uses --force-local flag ✅ Fixed
 
-**Expected Result:**
-- Should fail with error: "Remote 'nonexistent' does not exist"
-- Should suggest available remotes
-
----
-
-### Test 8: Local issues branch already exists
-**Setup:**
-```bash
-# Create repository with existing local issues branch
-mkdir test-tissue-8
-cd test-tissue-8
-git init
-echo "# Test Repo" > README.md
-git add README.md
-git commit -m "Initial commit"
-git checkout -b issues
-echo "# Existing Issues" > issues.md
-git add issues.md
-git commit -m "Existing issues branch"
-git checkout main
-```
-
-**Test:**
-```bash
-tissue init
-```
-
-**Expected Result:**
-- Should fail with error: "issues branch already exists - use 'tissue status' to check current setup"
-
----
-
-### Test 9: Local issues branch exists but worktree is missing
-**Setup:**
-```bash
-# Create repository with existing local issues branch but no worktree
-mkdir test-tissue-9
-cd test-tissue-9
-git init
-echo "# Test Repo" > README.md
-git add README.md
-git commit -m "Initial commit"
-git checkout -b issues
-echo "# Existing Issues" > issues.md
-git add issues.md
-git commit -m "Existing issues branch"
-git checkout main
-# Remove any existing worktree if present
-rm -rf issues/
-```
-
-**Test:**
-```bash
-tissue init
-```
-
-**Expected Result:**
-- Should detect existing local issues branch
-- Should checkout the existing branch (not create a new orphan)
-- Should set up worktree pointing to the existing branch
-- Success message: "Using existing 'issues' branch and setting up worktree"
-
-**Status:** ✅ Fixed
-- Now correctly detects and reuses existing local branches
-- Checks if worktree exists before creating branch
-- Skips branch creation if local branch exists
-
----
-
-### Test 10: Remote connectivity issues (SSH errors)
-**Setup:**
-```bash
-# Clone a repository that has an issues branch on remote
-# but SSH known_hosts has changed
-git clone git@github.com:example/repo.git test-tissue-10
-cd test-tissue-10
-# Simulate SSH key mismatch by corrupting known_hosts
-```
-
-**Test:**
-```bash
-tissue init
-```
-
-**Expected Result:**
-- Should detect that remote checking failed due to connectivity
-- Should NOT automatically create a new orphan branch
-- Should either:
-  - Error out with message: "Could not verify remote branches due to SSH error. Please fix SSH connectivity or use --force-local to create local branch anyway"
-  - OR prompt user for confirmation before creating local branch
-
-**Status:** ✅ Fixed
-- Added `--force-local` flag to bypass remote checks
-- Tracks which remotes failed to connect
-- Shows clear warnings about SSH connectivity issues
-- Simplified SSH handling - relies on go-git native authentication
-- Fails silently on remote connectivity issues unless critical
-
-## Expected User Experience
-
-### Scenario 1: Fresh repository, single remote
-```bash
-$ tissue init
-Initializing tissue issue tracking...
-Creating orphan 'issues' branch...
-Pushing to remote 'origin'...
-✓ Tissue initialized successfully!
-```
-
-### Scenario 2: Multiple remotes, no issues branch
-```bash
-$ tissue init
-Initializing tissue issue tracking...
-Creating orphan 'issues' branch...
-✓ Tissue initialized successfully!
-
-Multiple remotes detected. Not pushing to any remote.
-To push to a specific remote, run:
-  tissue init --remote <remote-name>
-
-Or push manually with git:
-  git push -u <remote-name> issues
-```
-
-### Scenario 3: Multiple remotes, one has issues branch
-```bash
-$ tissue init
-Initializing tissue issue tracking...
-Found existing 'issues' branch on remote 'origin'
-Fetching and tracking remote branch...
-✓ Tissue initialized successfully!
-```
-
-### Scenario 4: Multiple remotes, multiple have issues branch
-```bash
-$ tissue init
-Initializing tissue issue tracking...
-Error: Branch 'issues' exists on multiple remotes: [origin, upstream]. Use --remote flag to specify which remote to use
-```
-
-## Notes
-
-- Consider using go-git's native remote listing capabilities instead of exec'ing git commands
-- May need to handle authentication for remote operations more gracefully
-- Should respect user's git configuration for default push behavior
-- Consider adding a `tissue init --from-remote` command to explicitly pull existing issues branch
 
 ## Implementation Updates
 
@@ -717,8 +97,3 @@ Error: Branch 'issues' exists on multiple remotes: [origin, upstream]. Use --rem
 - Added `--force-local` flag to bypass remote checks when needed
 - Fail silently on SSH errors rather than blocking initialization
 
-## References
-
-- Current implementation: cmd/init.go:210-227
-- go-git remote handling: https://github.com/go-git/go-git/blob/master/remote.go
-- Git worktree documentation: https://git-scm.com/docs/git-worktree
003_git-user-config.md
@@ -0,0 +1,51 @@
+---
+id: 003
+title: Use git-configured user for commits
+status: open
+type: enhancement
+priority: low
+tags: [init, git-config]
+assignee:
+created: 2025-09-27T18:00:00Z
+updated: 2025-09-27T18:00:00Z
+---
+
+# Use git-configured user for commits
+
+## Problem Description
+
+The `tissue init` command currently hardcodes the commit author as "Tissue CLI" with email "tissue@example.com" when creating the initial commit on the issues branch. This should instead use the user's git configuration.
+
+## Current Behavior
+
+```go
+// Hardcoded in cmd/init.go
+Author: &object.Signature{
+    Name:  "Tissue CLI",
+    Email: "tissue@example.com",
+    When:  time.Now(),
+}
+```
+
+## Expected Behavior
+
+- Read `user.name` and `user.email` from git config
+- If not configured, prompt user to configure (similar to git's behavior)
+- Use the configured values for all commits made by tissue
+
+## Implementation Notes
+
+- Use go-git's config reading capabilities to get user settings
+- Check global config first, then local repo config
+- If neither is set, show error message with instructions:
+  ```
+  Please configure your git user:
+    git config --global user.name "Your Name"
+    git config --global user.email "your.email@example.com"
+  ```
+
+## Acceptance Criteria
+
+- Commits use the git-configured user name and email
+- Clear error message if git user is not configured
+- No hardcoded "Tissue CLI" author in commits
\ No newline at end of file
003_init-nits.md → 004_init-nits.md
File renamed without changes