Repository navigation
Conversation
…ence 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>
…erence 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>
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>
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>
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>
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>
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>
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>
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>
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>
|
|
||
| - **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. |
There was a problem hiding this comment.
🛠️ Consistent test guidance: Table-first advice can repeat the requested restyling detour. The confirmed repository preference keeps cases individually defined while existing command tests reuse shared setup; the old table-example pointer reinforces the superseded direction.
| - 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. |
There was a problem hiding this comment.
🛠️ Consistent Copilot entry point: This instruction can independently steer new cases into loops that have already required a requested rewrite. Individually defined cases can retain the existing shared-setup pattern without changing mock restoration or validation requirements.
| - 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. |
There was a problem hiding this comment.
🧹 Accurate setup lifecycle: Wrong prompt timing and storage assumptions can send maintenance work to the wrong place: init calls setup before its operation, the helper skips noninteractive use, and decline is Git configuration. The incidental loop ceiling remains at its definition.
| 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 |
There was a problem hiding this comment.
🛠️ Explicit setup expectations: Assuming init enabled rerere can leave unattended workflows without remembered resolutions; noninteractive setup deliberately skips enablement. The explicit configuration command and interactive confirmation advice stay.
| 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 |
There was a problem hiding this comment.
🛠️ Reliable recovery expectations: The replay guarantee and dependent layer explanation rely on configuration that noninteractive init does not establish. Manual recovery and the independent warning remain, with explicit setup still available.
| | `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. |
There was a problem hiding this comment.
🧹 Prompt-free state reading: Calling short view safe can lead an unattended agent into ordinary stack lookup and its shared-trunk selector. The existing JSON table entry already preserves the agent action; human short-format advice remains in the reference.
| ## Navigation | ||
|
|
||
| `up`, `down`, `top`, `bottom`, and `trunk` are always non-interactive. `up` and `down` accept a | ||
| `up` and `down` accept a |
There was a problem hiding this comment.
🛠️ Conditional navigation prompts: An unconditional guarantee can make unattended navigation wait for input. Ordinary navigation loads the stack through the interactive ambiguity resolver; count syntax and the checked path-mode procedure stay.
| `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. |
There was a problem hiding this comment.
🛠️ Correct editing destination: An unmerged layer can still be queued, so the old wording can point readers at a different branch than navigation selects. Bottom uses the first active index, whose definition excludes merged and queued layers. The existing active-branch condition is preserved.
|
|
||
| ## Branch placement | ||
|
|
||
| - **Starting multi-part work:** create the stack before writing files. Do not implement every |
There was a problem hiding this comment.
🧹 One complete planning procedure: Maintaining the same duties twice adds drift without another reader action. The already-required stack-design reference preserves dependency order and creation before editing and concern-specific commits. Existing-stack editing remains separate.
| 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 |
There was a problem hiding this comment.
🧹 One complete restructuring procedure: This shorter recipe adds upkeep to a procedure readers already must load when restructuring. The surviving recipe keeps the same limitation and action plus ancestry and preservation prerequisites; root editor and recorded-owner recovery warnings stay.
There was a problem hiding this comment.
🟡 Changes recommended
The command reference still leaves conditional rerere behavior unclear and incorrectly implies that bottom skips queued branches.
2 open issues
What changed in this PR
Updates gh-stack’s contributor and agent documentation to reduce stale guidance and unintended interactive workflows.
Changes:
- Aligns both instruction entry points on individually defined tests with shared setup helpers.
- Revises rerere and navigation descriptions to remove blanket behavior guarantees.
- Trims duplicated guidance from the main skill document.
| File | Description |
|---|---|
skills/gh-stack/SKILL.md |
Removes repeated output, branch-placement, and restructuring advice. |
skills/gh-stack/references/troubleshooting.md |
Removes the guarantee that init enables automatic conflict replay. |
skills/gh-stack/references/commands.md |
Revises rerere setup and navigation descriptions. |
AGENTS.md |
Updates test guidance and removes stale rerere details. |
.github/copilot-instructions.md |
Aligns testing instructions with the individual-test convention. |
Review effort: Max
| Under a TTY the first run in a repo asks for confirmation; set | ||
| `git config rerere.enabled true` beforehand to skip it. |
| `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. |

🧠 How this helps Copilot
The current test instructions steer Copilot toward table-driven loops, which have already required a requested rewrite. Aligning both instruction entry points with the repository's preference for individually defined test cases avoids that rework while preserving shared setup helpers and the existing validation requirements.
Unconditional prompt and conflict-replay guarantees can send unattended agents into input waits or leave them relying on configuration that was never enabled. More accurate navigation expectations also avoid sending edits to an unexpected branch. Keeping planning and restructuring procedures in their already-required references removes duplicate upkeep without dropping their prerequisites or recovery warnings.
Automated details
Source:
curate-memoriesDream, analyzingmainatbd0a325.