gitFlow/implementation.md
dimitar 012fbf8ac5 feat: phase 6 — polish: completions, notifications, themes, rules, docs
Close out the plan with the remaining polish items and a full README.

Shell completions (cmd/gitflow):
- New `completion [bash|zsh|fish|powershell]` command backed by cobra's
  generators, wired into the root command

Desktop notifications (internal/notify):
- Send() dispatches to notify-send (Linux) with an osascript fallback
  (macOS); Windows is a documented no-op for now; missing notifiers are
  silent, never errors
- watch --notify sends a notification listing repositories whose state
  changed since the previous frame

Color themes (internal/presenter):
- ThemeMode (dark/light) with ParseTheme; light uses bright ANSI variants
  (90-97) that stay legible on light backgrounds; threaded through the
  table, compact, and suggestions renderers; new --theme flag validated
  and dumped by config

Custom rules (internal/rules):
- Rule{name, field (ahead|behind|stash|changes), op (==,!=,<,<=,>,>=),
  value, label} with upfront validation in both Validate and Eval
- Config gains a `rules:` section (yaml/env only, no flag), validated at
  load; matches render as a "FLAGS (custom rules)" section via a new
  presenter.Flags renderer, shown in scan and watch frames

Docs:
- readme.md fully rewritten: features, install, usage, examples, flag
  table, status classes, configuration reference, AI agent behavior and
  --ai-execute guardrails, development layout, CI, and future work
- implementation.md gains an Implementation Progress section recording
  every phase branch and the deviations from the original plan

Multi-platform:
- Verified cross-compilation for windows/amd64 and darwin/arm64; the
  notify package is split behind build tags

Testing:
- rules: validation, operator semantics, Eval ordering, invalid-rule
  errors
- presenter: ParseTheme, light-theme bright codes (and absence of
  dark-theme codes), Flags rendering (empty = silent, matches render)
- config: rules loading from file, invalid-rule rejection, bad theme and
  bad provider rejection
- notify: no-op behaviour when no notifier is installed (skipped when one
  is, to avoid firing real notifications)

Verified: go build, go vet, go test -race (10 packages), gofmt clean,
windows/darwin cross-compile, completion generation, rules + light theme
smoke test, watch --notify graceful shutdown (exit 0, no orphans).
2026-08-02 08:52:50 +02:00

11 KiB
Raw Permalink Blame History

Git Flow — Detailed Development Plan

Overview

Git Flow is a Go CLI tool that discovers Git repositories under a user-specified parent directory, periodically scans their status, and presents findings with AI-driven suggestions for next actions (e.g., "commit pending changes", "push branch X", "pull latest from main").


Phase 0: Project Scaffolding & Tooling

Task Details Deliverable
Module init go mod init github.com/<user>/gitflow go.mod
Directory layout Flat-to-modular structure appropriate for a CLI (see layout below) Dir tree
Tooling Add golangci-lint config, Makefile, .gitignore Dev tooling
CI skeleton GitHub Actions: lint + test on push .github/workflows/ci.yml
gitflow/
├── cmd/gitflow/          # main entry point
├── internal/
│   ├── scanner/          # repo discovery + git status scanning
│   ├── presenter/        # output formatting (table, JSON, TUI)
│   ├── scheduler/        # periodic scan loop
│   ├── ai/               # AI agent integration
│   ├── config/           # CLI flags, env vars, config file parsing
│   └── git/              # thin wrappers around git commands
├── pkg/                  # shared types (RepoInfo, Status, etc.)
├── go.mod / go.sum
├── Makefile
├── .golangci.yml
└── readme.md

Phase 1: Core — Repo Discovery & Status Scanning

This is the foundational layer. Everything else depends on it.

1.1 Define the Domain Types (pkg/types.go or internal/scanner/types.go)

type RepoStatus int
const (
    StatusUnknown RepoStatus = iota
    StatusClean
    StatusModified
    StatusAhead
    StatusBehind
    StatusDiverged
    StatusDetached
    StatusBare
    StatusError
)

type RepoInfo struct {
    Path           string
    RemoteURL      string
    Branch         string
    Status         RepoStatus
    ModifiedFiles  []string
    StagedFiles    []string
    UntrackedFiles []string
    AheadBy        int
    BehindBy       int
    StashCount     int
    LastFetch      time.Time
    Error          string
}

type ScanResult struct {
    ScannedAt  time.Time
    ParentDir  string
    Repos      []RepoInfo
    TotalCount int
    ErrorCount int
}

1.2 Repo Discovery (internal/scanner/discover.go)

  • Walk the directory tree starting from the parent directory
  • Detect .git directories (including bare repos, submodules, worktrees)
  • Respect .gitignore-style exclusion patterns via a --exclude flag
  • Respect depth limits via a --depth / --max-depth flag
  • Use filepath.WalkDir for efficient traversal (no os.FileInfo allocations)

Pattern: Single-responsibility — the discoverer only finds repos; status scanning is a separate step.

1.3 Status Scanner (internal/scanner/status.go)

  • For each discovered repo, run git porcelain commands:
    • git status --porcelain -b for branch, ahead/behind, modified/staged/untracked
    • git remote -v for remote URL
    • git stash list for stash count
  • Parse output into RepoInfo
  • Resilience patterns from Go skill:
    • Timeout each git command (e.g., 10s via context.WithTimeout)
    • Handle repos with errors gracefully — mark as StatusError, don't crash
    • Run scans concurrently with a bounded worker pool (errgroup + semaphore)

1.4 Git Command Wrapper (internal/git/)

  • Thin wrapper: func Status(ctx context.Context, repoPath string) (RepoInfo, error)
  • Uses os/exec with context for cancellation/timeout
  • No external git library dependency — os/exec is sufficient for porcelain commands

Phase 2: CLI & Configuration

2.1 CLI Framework

Use Cobra + Viper (standard Go CLI stack):

Flag Type Default Description
--dir / -d string . (cwd) Parent directory to scan
--interval / -i duration 0 (run once) Rescan interval (e.g., 5m, 30s)
--format / -f string table Output format: table, json, compact
--exclude []string [] Glob patterns to exclude
--max-depth int 0 (unlimited) Max traversal depth
--ai bool false Enable AI suggestions
--ai-provider string openai AI backend
--ai-model string gpt-4o AI model
--watch / -w bool false Watch mode (alias for interval)

2.2 Configuration File

Support ~/.gitflow.yaml for defaults:

ai:
  provider: openai
  api_key_env: OPENAI_API_KEY
  model: gpt-4o
defaults:
  interval: 5m
  format: table
  exclude:
    - "node_modules"
    - "vendor"

2.3 Commands

gitflow scan          # one-shot scan
gitflow watch         # periodic scan (uses --interval)
gitflow config        # show/edit config
gitflow version       # version info

Phase 3: Presentation Layer

3.1 Table Output (default)

Rich terminal table using bubbletea / lipgloss (or simpler: tablewriter):

  REPOSITORY          BRANCH       STATUS     AHEAD/BEHIND   CHANGES
  ~/projects/api      main         ✓ clean         0 / 0        -
  ~/projects/web      feat/login   ✗ modified      3 / 0       2M, 1U
  ~/projects/lib      main         ⚠ behind        0 / 5        -
  ~/projects/legacy   (detached)   ⚠ detached      -           -

  4 repos scanned | 1 clean | 2 need attention | 2 errors

3.2 JSON Output

For scripting / piping:

{
  "scanned_at": "2026-01-01T12:00:00Z",
  "parent_dir": "/home/user/projects",
  "repos": [...],
  "summary": {"total": 4, "clean": 1, "attention": 2, "errors": 1}
}

3.3 Compact Output

One line per repo with color-coded status symbols.


Phase 4: Periodic Scanner (Scheduler)

4.1 Watch Mode (internal/scheduler/scheduler.go)

  • Runs scan on a time.Ticker at the configured interval
  • Clears terminal and re-renders (or uses TUI refresh)
  • Handles SIGINT/SIGTERM for graceful shutdown
  • Shows time until next scan in footer

Pattern: Use signal.NotifyContext for graceful shutdown. Defer cleanup immediately after resource acquisition.

4.2 Change Detection

  • Between scans, compare current vs previous ScanResult
  • Highlight repos that changed state
  • Optionally trigger desktop notifications (via beeep or notify-send)

Phase 5: AI Agent Integration

5.1 AI Module (internal/ai/)

Interface-first design (for testability and provider flexibility):

type Provider interface {
    Suggest(ctx context.Context, repos []RepoInfo) ([]Suggestion, error)
}

type Suggestion struct {
    RepoPath string
    Action   string   // "commit", "push", "pull", "stash", "pr", "cleanup"
    Message  string   // Human-readable suggestion
    Command  string   // Suggested git command to run
    Priority int      // 0=low, 1=medium, 2=high
}

5.2 Providers

  1. OpenAI (default): GPT-4o with structured output (JSON Schema) for reliable parsing
  2. Ollama (local/offline): Support for local models
  3. Anthropic Claude: Alternative cloud provider

5.3 Prompt Design

Construct a prompt that includes:

  • A summary table of all repos and their statuses
  • The top 3-5 repos needing attention
  • Instructions to output structured JSON with specific action types

5.4 AI Output Display

  • Show suggestions in a separate section below the status table
  • Color-coded by priority
  • Optional: --ai-execute flag to auto-run suggested commands (with confirmation)

Phase 6: Polish & Advanced Features

Feature Description
Color themes Light/dark terminal themes via lipgloss
TUI mode Full interactive TUI with bubbletea — navigate repos, expand details, trigger AI suggestions
Custom actions User-defined rules: "if behind > 10 commits, mark as critical"
Webhook/notifications Send alerts to Slack/Discord when repos need attention
Multi-platform Test on Linux, macOS, Windows (WSL)
Completion Shell completions for bash, zsh, fish via Cobra

Technology Choices Summary

Concern Choice Rationale
CLI framework Cobra + Viper Industry standard, completions, env binding
Git interaction os/exec (porcelain) No dependency needed; porcelain output is stable
TUI (optional) Bubble Tea + Lip Gloss Best Go TUI ecosystem
AI integration HTTP client + JSON Schema Provider-agnostic, no heavy SDK required
Concurrency errgroup + semaphore Bounded parallelism, error propagation
Testing testing + testify Standard + assertions
Linting golangci-lint Comprehensive Go linting

Milestone Schedule

Milestone Scope Estimated Effort
M1 — Skeleton Phase 0: module, layout, Makefile, CI 0.5 day
M2 — Discovery Phase 1: repo walker + git status parser 12 days
M3 — CLI Phase 2: Cobra commands, flags, config 1 day
M4 — Display Phase 3: table + JSON + compact output 1 day
M5 — Watch Phase 4: scheduler, auto-refresh, signals 1 day
M6 — AI Phase 5: provider interface, OpenAI, suggestions 12 days
M7 — Polish Phase 6: TUI, themes, completions, docs 23 days

Total estimated effort: ~710 days for a solid v1.0


Implementation Progress

All phases from this plan are implemented and merged into main (branch per phase, merged with --no-ff, no remote pushes).

Phase Branch Status
0 — Scaffolding feat/phase-0-scaffolding done
1 — Discovery & scanning feat/phase-1-discovery-scanning done
2 — CLI & configuration feat/phase-2-cli-config done
3 — Presentation feat/phase-3-presentation done
4 — Scheduler / watch feat/phase-4-scheduler done
5 — AI agent feat/phase-5-ai done
6 — Polish feat/phase-6-polish done

Deviations from the plan

  • LastFetch field dropped (phase 1): the only reliable source is a reflog of the remote-tracking ref, which does not exist on fresh clones; noted as future work instead.
  • Full bubbletea TUI deferred (phase 6): the plan listed it as optional; watch mode + completions + themes + notifications were implemented instead.
  • Webhooks deferred (phase 6): desktop notifications cover the alerting case; Slack/Discord noted as future work.
  • AI defaults: ai-model defaults to gpt-4o (plan) with provider-specific fallbacks (ollama → llama3.2, anthropic → claude-3-5-haiku-latest); --ai-execute implemented with an allowlist + per-command confirmation instead of a bare auto-run.
  • testify was not added: stdlib testing covers all suites, keeping the dependency tree minimal.