diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b3bb6c5..7ce5c02 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -48,13 +48,13 @@ To install the latest release (or test against a specific version): curl -fsSL https://raw.githubusercontent.com/jongio/grut/main/install.sh | sh # Specific version — Linux / macOS -curl -fsSL https://raw.githubusercontent.com/jongio/grut/main/install.sh | sh -s -- v0.1.0 +curl -fsSL https://raw.githubusercontent.com/jongio/grut/main/install.sh | sh -s -- v0.8.0 # Latest — Windows (PowerShell) irm https://raw.githubusercontent.com/jongio/grut/main/install.ps1 | iex # Specific version — Windows (PowerShell) -$v="v0.1.0"; irm https://raw.githubusercontent.com/jongio/grut/main/install.ps1 | iex +$v="v0.8.0"; irm https://raw.githubusercontent.com/jongio/grut/main/install.ps1 | iex ``` ## Development Workflow diff --git a/README.md b/README.md index 0de70d6..e870b8f 100644 --- a/README.md +++ b/README.md @@ -118,7 +118,7 @@ curl -fsSL https://raw.githubusercontent.com/jongio/grut/main/install.sh | sh To install a specific version: ```bash -curl -fsSL https://raw.githubusercontent.com/jongio/grut/main/install.sh | sh -s -- v0.1.0 +curl -fsSL https://raw.githubusercontent.com/jongio/grut/main/install.sh | sh -s -- v0.8.0 ``` ### PowerShell script (Windows) @@ -130,7 +130,7 @@ irm https://raw.githubusercontent.com/jongio/grut/main/install.ps1 | iex To install a specific version: ```powershell -$v="v0.1.0"; irm https://raw.githubusercontent.com/jongio/grut/main/install.ps1 | iex +$v="v0.8.0"; irm https://raw.githubusercontent.com/jongio/grut/main/install.ps1 | iex ``` ### Go Install @@ -243,6 +243,12 @@ Config file: `~/.config/grut/config.toml` (Linux/macOS) or `%APPDATA%\grut\confi See [docs/configuration.md](docs/configuration.md) for all options. +## Stability + +grut is pre-1.0, so pin a version if you depend on it in automation. See +[docs/stability.md](docs/stability.md) for what 1.0 will guarantee and what +still has to be documented before it is tagged. + ## Building from Source ```bash diff --git a/docs/specs/ai-git-ops/tasks.md b/docs/specs/ai-git-ops/tasks.md index ab3f4e8..94474a7 100644 --- a/docs/specs/ai-git-ops/tasks.md +++ b/docs/specs/ai-git-ops/tasks.md @@ -15,6 +15,8 @@ Enhance `internal/panels/branches/`: when AI enabled, stale/merged/abandoned bra The analysis engine already exists in `internal/ai/ops/branch.go` (task 12); only the panel wiring is outstanding. `ops.Branch` is currently referenced from no non-test panel code. +**Blocked on #418.** The wiring is not panel-local. `AnalyzeBranches` lives on the concrete `*middleware.AIGitClient` rather than the `git.GitClient` interface, panels are registered with the plain client before the AI client is built (`cmd/root.go:232` vs `:283`), and the layer that converts op results into panel messages does not exist yet. The same gap blocks six other shipped ops, so the access pattern should be decided once in #418 rather than invented here. + ## IN PROGRESS (none) diff --git a/docs/stability.md b/docs/stability.md new file mode 100644 index 0000000..f1a868e --- /dev/null +++ b/docs/stability.md @@ -0,0 +1,86 @@ +# Stability and Versioning + +grut is pre-1.0. This document says what that means today, what will be +guaranteed at 1.0, and what has to be true before 1.0 is worth tagging. + +## Today (0.x) + +Anything can change in a minor release. In practice the CLI surface has been +additive for several releases, but nothing here is promised yet, so pin a +version if you depend on grut in automation: + +```bash +curl -fsSL https://raw.githubusercontent.com/jongio/grut/main/install.sh | sh -s -- v0.8.0 +``` + +## What 1.0 will cover + +At 1.0 the following become part of the compatibility surface. Breaking any of +them requires a major version bump. + +### Command and flag names +The subcommands (`clean`, `completion`, `config`, `doctor`, `ext`, `keys`, +`mcp`, `report`, `run`, `status`, `theme`, `update`, `version`) and their +flags. Flags may be added; existing ones keep their meaning. + +### Machine-readable output +Ten commands emit structured output behind `--json`, fourteen flags in total +once subcommands are counted. Once 1.0 lands, the shape of that output is a +contract: fields may be added, but existing fields will not be removed, +renamed, or change type. + +### Exit codes +`--check` on `clean`, `doctor`, and `status` is an exit-code gate intended for +CI. Zero means the checked condition holds, non-zero means it does not. Scripts +depending on that distinction will keep working. + +### Configuration keys +The TOML keys documented in [configuration.md](configuration.md). Keys may be +added. Removing or repurposing one is breaking. + +Unknown keys are ignored rather than rejected, so a config written for a newer +grut still loads on an older one, minus the unrecognized settings. + +### Extension API +The `extension.toml` manifest schema, the permission model, and the Lua and +WASM host functions in [extensions.md](extensions.md). Third-party extensions +are the surface most expensive to break, since the author is not us. + +### Default keybindings +Default bindings will not be reassigned to different actions in a minor +release. Adding a binding to a previously unbound key is not breaking. + +## What 1.0 will not cover + +- **Go packages under `internal/`.** Go forbids importing these from outside + the module, so they are not an API. They can be restructured at any time. +- **TUI rendering.** Panel layout, colours, spacing, and glyphs are + presentation, not contract. Themes exist for callers who care. +- **Log and audit line formats**, unless a specific format is documented as + machine-readable. +- **Prerelease and dev builds.** + +## Before tagging 1.0 + +Freezing a surface is only meaningful if the surface is written down. Current +gaps: + +- [ ] **Document every `--json` shape.** Two of the ten commands are documented + today ([report-json.md](report-json.md), + [version-json.md](version-json.md)). The rest are contracts by accident + rather than by description. +- [ ] **Document the `--check` exit codes**, including what non-zero means for + each command. +- [ ] **Audit config keys for dead settings.** A key that is declared but + unread becomes a permanent obligation at 1.0. `socket_auth` was one of + these and has been removed; the rest of the schema deserves the same + pass. +- [ ] **Version the extension manifest.** Third-party extensions need a way to + declare which schema they target. +- [ ] **State the supported platform and Go version floor.** + +## Deprecation + +After 1.0, anything on the covered surface that is going away gets deprecated +before removal: it keeps working for at least one minor release, warns when +used, and the release notes name the replacement. \ No newline at end of file diff --git a/internal/git/doc.go b/internal/git/doc.go index 9b0be43..828e9e9 100644 --- a/internal/git/doc.go +++ b/internal/git/doc.go @@ -3,10 +3,33 @@ // OpQueue to prevent concurrent writes from corrupting repository state. // Read operations run concurrently against the same queue. // -// TODO(arch): This package has grown to 27+ files spanning 15+ distinct -// domains (blame, bisect, branch, diff, difftree, log, merge, queue, reflog, -// remote, reset, revert, stage_patch, stash, tag, undo, url, worktree). -// A future refactor should split it into sub-packages (e.g. git/branch, -// git/stash, git/log) to restore single-responsibility at the package level. -// See https://github.com/jongio/grut/issues/167 for context. +// On the file count: this package spans many domains (blame, bisect, branch, +// diff, difftree, log, merge, queue, reflog, remote, reset, revert, +// stage_patch, stash, tag, undo, url, worktree), and an automated review +// (issue #167) flagged that as a god package to be split into sub-packages. +// It is deliberately not split, for three reasons. +// +// First, Go does not permit it directly. Every domain file holds methods on +// *Client, and methods cannot be declared on a type owned by another package. +// Splitting would mean either fragmenting Client into per-domain clients, +// which destroys the single GitClient interface that the AI middleware +// implements and every panel consumes, or demoting the methods to free +// functions, which changes every call site and leaves the sub-packages +// importing git for the Client type anyway. +// +// Second, the shared state is the point. Client carries one OpQueue and one +// Cache. Serialisation and caching are correctness properties that hold +// across domains: a branch operation and a stash operation must not race. +// Per-domain packages would each need a reference back to that shared state, +// so the coupling would move rather than disappear. +// +// Third, the cost is not being paid. The package is roughly 4,000 lines +// across 30 files, averaging under 140 lines each, already separated by +// domain and named for it. Navigation happens by file, and the file layout is +// exactly the split the review asked for. +// +// The signal worth watching is file size rather than file count. If a single +// domain file outgrows ~500 lines, split that file. If a domain grows genuine +// state of its own, independent of the queue and cache, that is the point to +// reconsider a sub-package for it. package git