From 5d11ab7f315358b7218db3e57a7aa5081eb6e15b Mon Sep 17 00:00:00 2001 From: Copilot <223556219+Copilot@users.noreply.github.com> Date: Sat, 7 Nov 2026 14:11:10 +0000 Subject: [PATCH 01/10] [Copilot Dreams] Align agent test guidance with the repository preference The table-first instruction can steer new command coverage into loop-based cases that have already required a requested rewrite. Use individually named test functions while retaining shared setup, consistent with the confirmed repository-scoped preference. Existing command tests demonstrate the reusable setup pattern without requiring tables: https://github.com/github/gh-stack/blob/bd0a32504f9ae9f795875a9e6bb90ff7408fda08/cmd/sync_test.go#L1772-L1793 https://github.com/github/gh-stack/blob/bd0a32504f9ae9f795875a9e6bb90ff7408fda08/cmd/sync_test.go#L1798-L1830 The old example pointer reinforces the superseded table-first direction, so it is removed with that direction. Assertion framework, mock restoration, config, and validation requirements remain unchanged. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- AGENTS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AGENTS.md b/AGENTS.md index 1edf0dd..43d6797 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{...}`. From f9c01c841b39336df9b3888f4999fa18147c5669 Mon Sep 17 00:00:00 2001 From: Copilot <223556219+Copilot@users.noreply.github.com> Date: Sat, 7 Nov 2026 14:11:10 +0000 Subject: [PATCH 02/10] [Copilot Dreams] Align Copilot test guidance with the repository preference The concise Copilot instructions can independently steer new cases into table-driven loops, despite the confirmed repository-scoped preference that already required two test blocks to be rewritten. State the individual-test direction at this entry point as well, retaining reusable setup. Existing command tests provide a shared setup helper and call it from an individually named test: https://github.com/github/gh-stack/blob/bd0a32504f9ae9f795875a9e6bb90ff7408fda08/cmd/sync_test.go#L1772-L1793 https://github.com/github/gh-stack/blob/bd0a32504f9ae9f795875a9e6bb90ff7408fda08/cmd/sync_test.go#L1798-L1830 The correction does not change framework selection, mock restoration, captured I/O, or the restrictions on parallel tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/copilot-instructions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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{...}`. From b2dcfa7f2e503d8666ae4eb9673fc9fab3bb8627 Mon Sep 17 00:00:00 2001 From: Copilot <223556219+Copilot@users.noreply.github.com> Date: Sat, 7 Nov 2026 14:11:10 +0000 Subject: [PATCH 03/10] [Copilot Dreams] Keep rerere lifecycle expectations accurate The first-conflict prompt and declined-state file description can send maintainers toward the wrong lifecycle and storage mechanism. The helper is called before the operation, skips noninteractive use, and saves decline in Git configuration: https://github.com/github/gh-stack/blob/bd0a32504f9ae9f795875a9e6bb90ff7408fda08/cmd/init.go#L84-L86 https://github.com/github/gh-stack/blob/bd0a32504f9ae9f795875a9e6bb90ff7408fda08/cmd/utils.go#L1893-L1923 https://github.com/github/gh-stack/blob/bd0a32504f9ae9f795875a9e6bb90ff7408fda08/internal/git/gitops.go#L383-L385 Remove this implementation-narration item rather than prescribe a new prompt policy. Its true loop ceiling is incidental detail maintained at the named definition, not an independent reader duty: https://github.com/github/gh-stack/blob/bd0a32504f9ae9f795875a9e6bb90ff7408fda08/internal/git/git.go#L181-L215 Explicit setup and conflict recovery remain in the agent skill. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- AGENTS.md | 1 - 1 file changed, 1 deletion(-) diff --git a/AGENTS.md b/AGENTS.md index 43d6797..5c6ba7b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -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). From d4282a5be8d088ee59eef60db798fa90ff0c330e Mon Sep 17 00:00:00 2001 From: Copilot <223556219+Copilot@users.noreply.github.com> Date: Sat, 7 Nov 2026 14:11:10 +0000 Subject: [PATCH 04/10] [Copilot Dreams] Preserve explicit rerere setup expectations Assuming init enabled rerere can leave unattended workflows without remembered conflict resolutions. The helper deliberately skips noninteractive enablement, with a regression proving that behavior: https://github.com/github/gh-stack/blob/bd0a32504f9ae9f795875a9e6bb90ff7408fda08/cmd/utils.go#L1893-L1923 https://github.com/github/gh-stack/blob/bd0a32504f9ae9f795875a9e6bb90ff7408fda08/cmd/utils_test.go#L1094-L1122 Remove the unguaranteed enablement narration while retaining the following interactive confirmation description and explicit configuration command. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- skills/gh-stack/references/commands.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/skills/gh-stack/references/commands.md b/skills/gh-stack/references/commands.md index 54fd09a..2af8d1b 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 From 0dbb6941362a0891737b293795b34b4b290c9448 Mon Sep 17 00:00:00 2001 From: Copilot <223556219+Copilot@users.noreply.github.com> Date: Sat, 7 Nov 2026 14:11:10 +0000 Subject: [PATCH 05/10] [Copilot Dreams] Keep conflict recovery independent of implicit setup The replay guarantee can cause an agent to rely on configuration that init never established in noninteractive use: https://github.com/github/gh-stack/blob/bd0a32504f9ae9f795875a9e6bb90ff7408fda08/cmd/utils.go#L1893-L1923 https://github.com/github/gh-stack/blob/bd0a32504f9ae9f795875a9e6bb90ff7408fda08/cmd/utils_test.go#L1094-L1122 The repeated-layer explanation depends on that guarantee and supplies no independent reader action. Keep the manual recovery sequence and the warning about repeated conflicts without rerere. Explicit setup still lives here: https://github.com/github/gh-stack/blob/bd0a32504f9ae9f795875a9e6bb90ff7408fda08/skills/gh-stack/SKILL.md#L34-L38 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- skills/gh-stack/references/troubleshooting.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) 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 From 96f6e74d429bb1ffa09512ecd7e3c048829f317d Mon Sep 17 00:00:00 2001 From: Copilot <223556219+Copilot@users.noreply.github.com> Date: Sat, 7 Nov 2026 14:11:10 +0000 Subject: [PATCH 06/10] [Copilot Dreams] Keep unattended view guidance on the prompt-free path Calling short view safe under both terminal modes can steer an unattended agent into shared-trunk stack selection. Short view uses ordinary stack lookup, while JSON has a separate path that returns an ambiguity error: https://github.com/github/gh-stack/blob/bd0a32504f9ae9f795875a9e6bb90ff7408fda08/cmd/view.go#L62-L76 https://github.com/github/gh-stack/blob/bd0a32504f9ae9f795875a9e6bb90ff7408fda08/cmd/utils.go#L444-L471 https://github.com/github/gh-stack/blob/bd0a32504f9ae9f795875a9e6bb90ff7408fda08/cmd/view.go#L123-L138 The verified JSON invocation already survives in the root command table: https://github.com/github/gh-stack/blob/bd0a32504f9ae9f795875a9e6bb90ff7408fda08/skills/gh-stack/SKILL.md#L49-L59 Human-oriented short-format advice remains in the command reference, so the removed item adds no independent action. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- skills/gh-stack/SKILL.md | 1 - 1 file changed, 1 deletion(-) diff --git a/skills/gh-stack/SKILL.md b/skills/gh-stack/SKILL.md index 8e39024..0d33ffa 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 From 64439f050526b9e892ae3c87cf453cc6de6bb441 Mon Sep 17 00:00:00 2001 From: Copilot <223556219+Copilot@users.noreply.github.com> Date: Sat, 7 Nov 2026 14:11:10 +0000 Subject: [PATCH 07/10] [Copilot Dreams] Keep navigation prompt expectations conditional The unconditional guarantee can make an unattended agent choose a navigation invocation that waits for shared-trunk selection. Ordinary navigation loads the stack through the interactive resolver; only explicit path mode selects a noninteractive config: https://github.com/github/gh-stack/blob/bd0a32504f9ae9f795875a9e6bb90ff7408fda08/cmd/navigate.go#L112-L119 https://github.com/github/gh-stack/blob/bd0a32504f9ae9f795875a9e6bb90ff7408fda08/cmd/worktree_utils.go#L304-L307 https://github.com/github/gh-stack/blob/bd0a32504f9ae9f795875a9e6bb90ff7408fda08/cmd/utils.go#L444-L471 Remove only the refuted guarantee. Count syntax, movement rules, the menu-only switch warning, and the checked path-mode procedure remain. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- skills/gh-stack/references/commands.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/skills/gh-stack/references/commands.md b/skills/gh-stack/references/commands.md index 2af8d1b..e6476fb 100644 --- a/skills/gh-stack/references/commands.md +++ b/skills/gh-stack/references/commands.md @@ -190,7 +190,7 @@ 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. From fa464f1f1afc991eaa5a9e32e0e63de96d5b2140 Mon Sep 17 00:00:00 2001 From: Copilot <223556219+Copilot@users.noreply.github.com> Date: Sat, 7 Nov 2026 14:11:10 +0000 Subject: [PATCH 08/10] [Copilot Dreams] Match bottom navigation guidance to its destination Describing the destination as merely unmerged includes queued layers that bottom skips, so a reader can expect to edit a different branch. Bottom uses the first active branch, which excludes merged and queued layers: https://github.com/github/gh-stack/blob/bd0a32504f9ae9f795875a9e6bb90ff7408fda08/cmd/navigate.go#L261-L270 https://github.com/github/gh-stack/blob/bd0a32504f9ae9f795875a9e6bb90ff7408fda08/internal/stack/stack.go#L110-L124 https://github.com/github/gh-stack/blob/bd0a32504f9ae9f795875a9e6bb90ff7408fda08/internal/stack/stack.go#L149-L157 Only the result-category token changes. The existing active-branch condition excludes the all-inactive fallback; clamping and merged-branch skipping stay. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- skills/gh-stack/references/commands.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/skills/gh-stack/references/commands.md b/skills/gh-stack/references/commands.md index e6476fb..9e60f73 100644 --- a/skills/gh-stack/references/commands.md +++ b/skills/gh-stack/references/commands.md @@ -192,7 +192,7 @@ Removes the stack **grouping** only. It never deletes pull requests or branches. `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. From 6305463b8285a609a6537c014824a977d0383e66 Mon Sep 17 00:00:00 2001 From: Copilot <223556219+Copilot@users.noreply.github.com> Date: Sat, 7 Nov 2026 14:11:10 +0000 Subject: [PATCH 09/10] [Copilot Dreams] Keep stack planning in its complete procedure Two maintained copies of the same planning duties can drift without adding an agent action. The root skill already mandates the stack-design reference before creation: https://github.com/github/gh-stack/blob/bd0a32504f9ae9f795875a9e6bb90ff7408fda08/skills/gh-stack/SKILL.md#L187-L190 That procedure covers dependency order, creating before editing rather than splitting later, and keeping each layer's changes on its branch: https://github.com/github/gh-stack/blob/bd0a32504f9ae9f795875a9e6bb90ff7408fda08/skills/gh-stack/references/stack-design.md#L15-L35 https://github.com/github/gh-stack/blob/bd0a32504f9ae9f795875a9e6bb90ff7408fda08/skills/gh-stack/references/stack-design.md#L52-L67 Remove only the shorter restatement. The distinct existing-stack editing procedure, its heading, and the reference invocation remain unchanged. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- skills/gh-stack/SKILL.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/skills/gh-stack/SKILL.md b/skills/gh-stack/SKILL.md index 0d33ffa..176e2e9 100644 --- a/skills/gh-stack/SKILL.md +++ b/skills/gh-stack/SKILL.md @@ -67,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, From 961fa92f3d0d0b54f446b48c7de6d9b96fa76d0a Mon Sep 17 00:00:00 2001 From: Copilot <223556219+Copilot@users.noreply.github.com> Date: Sat, 7 Nov 2026 14:11:10 +0000 Subject: [PATCH 10/10] [Copilot Dreams] Keep restructuring in its complete recovery procedure The shorter root recipe duplicates a procedure readers already must load, adding upkeep without preserving an independent duty. The root explicitly mandates troubleshooting when restructuring: https://github.com/github/gh-stack/blob/bd0a32504f9ae9f795875a9e6bb90ff7408fda08/skills/gh-stack/SKILL.md#L193-L194 The survivor supplies the same TUI limitation and unstack/init action, plus branch preservation, PR preservation, and the Git-ancestry prerequisite: https://github.com/github/gh-stack/blob/bd0a32504f9ae9f795875a9e6bb90ff7408fda08/skills/gh-stack/references/troubleshooting.md#L82-L115 Keep the root's bare-editor and recorded-owner recovery warnings, which have different triggers. No restructuring behavior changes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- skills/gh-stack/SKILL.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/skills/gh-stack/SKILL.md b/skills/gh-stack/SKILL.md index 176e2e9..6db5082 100644 --- a/skills/gh-stack/SKILL.md +++ b/skills/gh-stack/SKILL.md @@ -172,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