diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index e5adc47..96ed873 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -32,7 +32,7 @@ No Makefile, no code generation, no external linter config. Standard Go toolchai - Return typed `ExitError` sentinels (codes 1-10 in `cmd/utils.go`) from `RunE`. Never call `os.Exit()` directly. - Check errors with `var exitErr *ExitError; errors.As(err, &exitErr)`. -- Table-driven tests with `t.Run()` subtests. +- Define each test case as an individual `Test...` function, sharing setup helpers where useful. - Use `config.NewTestConfig()` for test configs with captured I/O. - Mock git: `restore := git.SetOps(&git.MockOps{...}); defer restore()`. Always defer restore. - Mock GitHub: `cfg.GitHubClientOverride = &github.MockClient{...}`. diff --git a/AGENTS.md b/AGENTS.md index 1edf0dd..5c6ba7b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -103,7 +103,7 @@ if errors.As(err, &exitErr) { ... } ### Testing patterns - **Framework:** `stretchr/testify` (`assert`, `require`) for assertions. -- **Table-driven tests** are the norm. See `cmd/utils_test.go` for examples. +- **Test cases:** Define each case as an individual `Test...` function, sharing setup helpers where useful. - **Config:** Use `config.NewTestConfig()` which returns `(*Config, stdoutReader, stderrReader)` with captured I/O and no-op color functions. - **Git mocking:** Call `git.SetOps(&git.MockOps{...})`. It returns a restore function. Always `defer restore()` to prevent test pollution. - **GitHub mocking:** Set `cfg.GitHubClientOverride = &github.MockClient{...}`. @@ -144,7 +144,6 @@ if errors.As(err, &exitErr) { ... } - The `Queued` field on `BranchRef` is transient (populated from GitHub API, never persisted to the stack JSON file). - `git.SetOps()` replaces the **package-level** ops variable. Forgetting `defer restore()` in a test will break every subsequent test in the package. - Interrupt detection: Ctrl+C is caught as `terminal.InterruptErr`, wrapped into an `errInterrupt` sentinel, and printed with a friendly message before a silent exit. -- Rerere: on first rebase conflict, the user is prompted to enable `git rerere`. If declined, a flag file prevents future prompts. `tryAutoResolveRebase()` loops up to 1000 times auto-continuing when rerere resolves conflicts. - Rebase commands disable automatic maintenance through command-local configuration so detached `rerere gc` cannot race conflict handling. Repository settings and unrelated Git commands are unchanged. - Date-preserving rebase starts use the merge backend so Git persists the date setting across conflicts. Continuations use native saved settings, not start-only date flags. - The `.gitignore` ignores `/gh-stack` and `/gh-stack.exe` (the built binary). diff --git a/skills/gh-stack/SKILL.md b/skills/gh-stack/SKILL.md index 8e39024..6db5082 100644 --- a/skills/gh-stack/SKILL.md +++ b/skills/gh-stack/SKILL.md @@ -58,7 +58,6 @@ Agent harnesses differ, so always pass the flags below instead of relying on tha | `gh stack up` / `down` / `top` / `bottom` | `gh stack switch` | `switch` is menu-only | | — | `gh stack modify` | TUI-only, no non-interactive path | -- `view --short` is safe in both modes, but it is formatted for humans. Use `--json` to parse. - **`checkout ` when a different local stack already covers those branches** cannot be forced. Run `gh stack unstack --local` first (this keeps the stack on GitHub), then retry. - **Worktrees:** local stacks share one common-directory catalog. Use `--print-path` with @@ -68,8 +67,6 @@ Agent harnesses differ, so always pass the flags below instead of relying on tha ## Branch placement -- **Starting multi-part work:** create the stack before writing files. Do not implement every - concern on trunk and split it later. Put one dependent concern in each layer, bottom to top. - **Editing an existing stack:** check out the layer that owns the change before editing. Never commit a lower layer's concern on the current top branch. Run `gh stack view --json`; if ownership is unclear, inspect `git log --all -- `. Then check out the owner, edit, commit, @@ -175,8 +172,6 @@ an ancestor of the branch. affected clean owners; unoccupied branches use the origin. Drop/fold source branches and worktrees are preserved. Recovery flags may run from any worktree and use recorded native operation owners; never resolve/stage in the caller's tree unless the diagnostic names it. -- There is no non-interactive reorder or removal. Errors may suggest `gh stack modify`, but it is - TUI-only — restructure with `unstack` then `init` instead. - PR titles and bodies are auto-generated. Use `gh pr edit` afterwards to change them. ## More detail diff --git a/skills/gh-stack/references/commands.md b/skills/gh-stack/references/commands.md index 54fd09a..9e60f73 100644 --- a/skills/gh-stack/references/commands.md +++ b/skills/gh-stack/references/commands.md @@ -31,7 +31,7 @@ branch does not exist, it is created from the trunk; each later new branch is cr branch immediately before it. There is no separate adopt mode — existence decides. `--base` selects a non-default trunk. -`init` also enables `git rerere`. Under a TTY the first run in a repo asks for confirmation; set +Under a TTY the first run in a repo asks for confirmation; set `git config rerere.enabled true` beforehand to skip it. ## add @@ -190,9 +190,9 @@ Removes the stack **grouping** only. It never deletes pull requests or branches. ## Navigation -`up`, `down`, `top`, `bottom`, and `trunk` are always non-interactive. `up` and `down` accept a +`up` and `down` accept a count (`gh stack up 3`). Movement clamps at the stack bounds, and merged branches are skipped when -navigating from an active branch, so `bottom` lands on the lowest *unmerged* branch. +navigating from an active branch, so `bottom` lands on the lowest *active* branch. `gh stack switch` is a selection menu with no non-interactive path. Use the commands above instead. diff --git a/skills/gh-stack/references/troubleshooting.md b/skills/gh-stack/references/troubleshooting.md index 774a459..8b4cdee 100644 --- a/skills/gh-stack/references/troubleshooting.md +++ b/skills/gh-stack/references/troubleshooting.md @@ -25,9 +25,7 @@ gh stack rebase --continue # repeat if the next branch also conflicts `gh stack rebase --abort` restores every branch in the stack, not just the current one. -Because `init` enables `git rerere`, a conflict you resolve once is replayed automatically the next -time the same conflict appears — which is common, since a change low in the stack is rebased through -every branch above it. Without `rerere`, repeated conflicts may need manual resolution on each +Without `rerere`, repeated conflicts may need manual resolution on each affected layer. ## After a squash merge