Repository navigation
Add git stack doctor to check and fix git-stack's setup - #69
Merged
Merged
Conversation
When something git-stack leans on is missing or in a state it can't work with, it only finds out part way through a command, and the error rarely says what to do: an old gh-stack, gh logged out, or stack files gh-stack 0.2 kept per worktree that make gh stack 0.3 stop with "cannot migrate stack catalogs". git stack doctor runs a list of checks, each with the checks that only make sense once it passes (gh-stack's version under gh-stack, under gh): git and its version, gh and its login, gh-stack and its version, git-stack's own aliases and whether a newer release is out, gh stack's stack file and whether any worktree still keeps its own, and in a repository an unfinished restack, tracked branches that are gone and an empty branch under others. Outside a repository the ones that need none still run. Each problem says what to do about it, and with --fix the ones git-stack can put right itself are fixed (install or upgrade gh-stack, set missing aliases without replacing any the user set, update git-stack, move the per worktree files into the shared one, forget branches that are gone) before everything is checked again. It exits non-zero while anything still fails. The checks live with what they check through a small doctor.Provider port: the backend checks gh and gh-stack, gitconfig the aliases, update the release, and the use case adds git and the stack checks. stack_doctor gives MCP clients the same, with the checks flattened (each naming its parent), outside a repository too, but reports a newer release rather than replacing the binary the server runs as. The server's instructions point not_installed and state_migration errors at it.
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved correctness and safety issues let doctor report success after failed repairs, block diagnostics when Git is missing, and advertise destructive MCP repairs as non-destructive.
6 open issues
Handle missing git without aborting doctor checks · New Preserve fix labels when repaired checks pass · New Mark fix errors as failed in doctor results · New Avoid false empty-branch warnings for existing PRs · New Direct catalog errors to the failing legacy file · New Mark repair-capable doctor tool as destructive · New
What changed in this PR
Adds git stack doctor and the matching stack_doctor MCP tool to diagnose setup and stack problems through shared application logic, with optional automatic repairs.
Changes:
- Introduces provider-based checks for dependencies, aliases, releases, stack files, and branch health.
- Adds repair-and-recheck execution, CLI tree output, and structured MCP results.
- Documents the feature and adds tests for checks, repairs, rendering, and MCP access.
| File | Description |
|---|---|
| README.md | Documents doctor checks and --fix. |
| pkg/update/doctor.go | Adds release checks and optional self-update. |
| pkg/update/doctor_test.go | Tests release reporting and update callbacks. |
| pkg/ui/report.go | Adds the doctor progress icon. |
| pkg/ui/doctor.go | Renders check trees and repair results. |
| pkg/ui/doctor_test.go | Tests plain-text rendering and escaping. |
| pkg/mcp/tools.go | Registers and handles stack_doctor. |
| pkg/mcp/server.go | Adds doctor providers and bare-app wiring. |
| pkg/mcp/server_test.go | Tests doctor registration and repository-independent checks. |
| pkg/mcp/instructions.go | Directs setup errors to doctor. |
| pkg/gitconfig/doctor.go | Checks aliases and installs missing ones. |
| pkg/gitconfig/doctor_test.go | Tests repairs preserving user aliases. |
| pkg/git/version_internal_test.go | Tests Git version parsing. |
| pkg/git/git.go | Adds version detection and the supported minimum. |
| pkg/doctor/doctor.go | Defines check contracts and flattened results. |
| pkg/backend/ghstack/doctor.go | Checks gh, authentication, extension versions, and catalogs. |
| pkg/backend/ghstack/doctor_test.go | Tests dependency checks and catalog migration. |
| pkg/app/doctor.go | Runs checks, repairs, and stack diagnostics. |
| pkg/app/doctor_test.go | Tests check dependencies, repairs, and branch diagnostics. |
| pkg/app/app.go | Adds provider dependencies and the doctor phase. |
| docs/style.md | Documents doctor progress presentation. |
| docs/mcp.md | Documents the MCP tool and result fields. |
| cmd/update.go | Extracts reusable updater setup helpers. |
| cmd/root.go | Registers doctor and supports bare-app construction. |
| cmd/mcp.go | Wires MCP providers without binary replacement. |
| cmd/doctor.go | Adds CLI flags, output, and exit handling. |
Review effort: Balanced
Comment on lines
+218
to
+220
| if se, ok := errors.AsType[*stack.Error](err); !ok || se.Kind != stack.KindNotRepo { | ||
| return nil, nil, err | ||
| } |
Comment on lines
+112
to
+113
| if c.Fix != nil && (f.Status == doctor.Fail || f.Status == doctor.Warn) { | ||
| r.Fix = c.FixLabel |
Comment on lines
+157
to
+158
| case err != nil: | ||
| r.FixError = errText(err) |
Comment on lines
+317
to
+318
| if err == nil && n == 0 && !b.Merged() && i < len(s.Branches)-1 { | ||
| empty = append(empty, b.Name) |
| c, err := readCatalog(repo) | ||
| if err != nil { | ||
| return doctor.Finding{Status: doctor.Fail, Summary: "can't read the stack file", Details: errLines(err), | ||
| Steps: []string{"fix or move aside " + catalogPath(repo) + ", then run git stack doctor again"}} |
| Name: "stack_doctor", | ||
| Title: "Check git-stack's setup", | ||
| Description: "Check that git-stack has what it needs and that the repository's stacks are in good shape: git and its version, gh and its login, the gh-stack extension and its version (v0.3.0 or later), gh stack's stack file (stacks still kept per worktree by gh-stack 0.2 make gh stack fail with state_migration), an interrupted restack, tracked branches that are gone and empty branches under others. Each check has a status (ok, warn, fail, skipped, fixed), a summary, details, next_steps and, when it can put it right itself, fix; checks that hang off a failing one are skipped. With fix: true it runs those fixes and checks again (fix_error says why one didn't work). Without repo_path and outside a repository only the checks that need no repository run. git-stack's own aliases and release are checked too, but updating git-stack is left to the user (git stack update). Call it when a tool fails with not_installed or state_migration.", | ||
| Annotations: &mcp.ToolAnnotations{DestructiveHint: boolp(false), OpenWorldHint: boolp(true)}, |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

When something git-stack leans on is missing or in a state it can't work with, we only find out part way through a command, and the error rarely says what to do about it: an old gh-stack, gh logged out, or the per worktree stack files from gh-stack 0.2 that make 0.3 stop with "cannot migrate stack catalogs".
git stack doctorruns a list of checks, each with the checks that only make sense once it passes (gh-stack's version hangs off gh-stack, which hangs off gh, so a missing gh doesn't also report a missing login). It looks at git and its version, gh and its login, gh-stack and its version, git-stack's own aliases and whether a newer release is out, gh stack's stack file and whether any worktree still keeps its own, and inside a repository an unfinished restack, tracked branches that are gone and an empty branch under others (outside a repository the rest still run). Every problem says what to do, and with--fixthe ones git-stack can put right itself are fixed (install or upgrade gh-stack, set the missing aliases without touching any you set yourself, update git-stack, move the per worktree files into the shared one, forget branches that are gone) before everything is checked again. It exits non-zero while anything still fails.The checks live with what they check through a small
doctor.Providerport: the backend does gh and gh-stack, gitconfig the aliases, update the release, and the use case adds git and the stack checks. MCP clients get the same asstack_doctor, with the checks flattened (each naming its parent, since the schema can't describe the tree) and outside a repository too, though it only reports a newer release rather than replacing the binary the server is running as. The server's instructions pointnot_installedandstate_migrationerrors at it.