Commit Graph

10 Commits

Author SHA1 Message Date
Sameen Karim 68ce60c760 Merge Stacked PRs with merge command (#307)
* merge cmd

* Refine the merge TUI and simplify the async-merge client

Follow-up polish for `gh stack merge` (the command itself landed in the
previous commit). These changes refine the interactive wizard, enrich the
PR picker, and replace the merge client's bespoke HTTP handling with the
standard go-gh REST client.

Wizard and stepper:
- Redesign the top stepper as a segmented bar: completed steps are green,
  the active step is the brightest, and upcoming steps are dimmed. Steps
  are separated by a Powerline arrow that blends into the shading, with a
  graceful fallback to abutting segments on terminals that lack the glyph
  (e.g. Apple Terminal). Set GH_STACK_POWERLINE=1/0 to override detection.
- Show the stack number in the header ("Merge stack #123").
- Hide the header and stepper once the merge is submitted so the live
  progress view stands on its own.

PR picker:
- Render each pull request on two lines: the title (white/black, a touch
  bolder when selected) above its "#number • branch" (gray, fainter when
  deselected). Titles are fetched in one batched GraphQL query (PRTitles)
  and fall back to the branch name.
- Scroll long stacks in a fixed 10-item window with persistent "N more"
  indicators, so the list no longer jumps as those hints appear and
  disappear. Add shift+up / shift+down to jump to the top or bottom.

Progress and outcome:
- Always render a status line ("Submitting merge request...") so it does
  not pop in later and shift the view, and normalize messages to end in an
  ellipsis.
- Print the final result from the command layer rather than the TUI: a
  success line that includes the merge commit SHA
  ("Merged #1, #2 into main (abc1234)"), an atomic-rollback note on
  failure, a distinct message when the user stops watching an in-flight
  merge, and "Cancelled operation, nothing merged" on cancel.
- Clamp every rendered line to the terminal width so resizing no longer
  leaves duplicated header lines behind, and make truncation ANSI-aware.

Async-merge client:
- Use the go-gh REST client (c.rest.Put / c.rest.Get) for both the submit
  and poll endpoints, removing the bespoke http.Client, base-URL helper,
  and manual response decoding. The REST client discards non-2xx bodies,
  but that only costs the rare 400 message and 409 UUID: real merge
  failures still surface through the 200 poll body, and the in-range PRs
  are validated open, non-draft, and non-merged before submitting.
- Add classifyAsyncMergeError to map status codes to clear errors (404
  unavailable, 409 already exists, 400 no longer mergeable) and drop the
  now-unused AsyncMergeResult.StatusCode field. Rework the client tests to
  drive the REST client through a stub http.RoundTripper.

* warn merge queue unsupported

* update for new status field from api

* merge cmd docs

* more helpful error msgs

* update to support merge queue

* addressing review comments

* hide merge method step for merge queue

* set merge action explicitly

* address review comments to clarify docs on merge/api behavior
2026-07-29 13:32:07 -04:00
Sameen Karim 53ed88c2a2 Docs Content Updates (#185)
* stack map and merge behavior clarification

* stacked webhook event

* stacks rest api

* optimizing ci usage

* graphql api docs

* rm deprecated adopt examples for init

* clarifications on merge behavior

* document admin bypass and auto-merge limitations

* updated screenshots

* unstacking behavior clarification

* stacking recommendation banner

* correct phrasing for bypass

* clarify wording on trunk branch

* skill file fixes

* bump js-yaml to 4.3.0

* fix broken link

* move up flag references for readability
2026-07-26 11:26:04 -04:00
Sameen Karim 797c62e9b4 Adapt theme colors to light and dark terminals (#149)
* Make the TUIs adapt to light and dark terminal backgrounds

The submit, view, and modify TUIs were tuned for dark terminals. On light
or solarized-light backgrounds the result was hard to read and inverted:
primary text used ANSI white (invisible on white), dim chrome used light
grays (too faint), and accents used bright cyan (low contrast) — so
"active" things looked lighter than "disabled" ones.

Introduce a centralized, background-aware color palette and migrate all
three TUIs to it:

- internal/tui/shared/theme.go: a semantic palette of lipgloss.AdaptiveColor
  values (primary/muted/faint text, chrome/border, accent, PR-state colors,
  badge backgrounds, row shade, button, switch). lipgloss resolves the
  light/dark variant per render from the terminal background, which Bubble
  Tea detects at startup; terminals that don't report it fall back to dark,
  preserving the original look.
- Replace every hardcoded ANSI color in shared/, submitview/, and
  modifyview/ with palette roles. The four pre-rendered status icons now
  render at use-time so their adaptive colors resolve correctly. The submit
  markdown preview picks glamour's light or dark style from the detected
  background.
- GH_STACK_THEME=auto|light|dark forces the palette for terminals that
  mis-detect (some SSH/tmux setups); wired via the root command's
  PersistentPreRun before any render. Documented in the README and CLI docs.

Neutral text/chrome use truecolor hex (GitHub Primer-inspired) for
predictability across themes, including solarized which repurposes ANSI
8-15; lipgloss downsamples on terminals without truecolor.

Tests verify the palette resolves differently for light vs dark and that
GH_STACK_THEME is honored.

* Apply background-aware colors to all command output

Background detection and the GH_STACK_THEME override (added for the TUIs)
only affected the interactive screens. Plain command output -- status
messages and interactive prompts -- went through the mgutz/ansi library
with fixed ANSI palette names (green/red/yellow/cyan/...), so it never
adapted to the terminal background and could read poorly on light or
solarized themes.

Unify everything on the same adaptive palette so all colors react to the
detected background and to GH_STACK_THEME.

- Extract internal/theme, a foundational package with no internal
  dependencies, that owns:
    - the background-aware lipgloss.AdaptiveColor palette (moved out of
      internal/tui/shared),
    - ApplyOverride(), the GH_STACK_THEME=auto|light|dark logic, and
    - non-TUI colorizers (Success/Error/Warning/Blue/Magenta/Cyan/Gray/
      Bold) plus FgSeqs(), which returns the raw start/reset escapes used
      to color the user's echoed prompt input.
- internal/tui/shared/theme.go now re-exports the palette, so the TUI code
  keeps referring to shared.ColorX unchanged.
- internal/config/config.go wires the Config.Color* funcs to the theme
  colorizers and drops mgutz/ansi (now an indirect dependency only).
- cmd/utils.go colors the prompt icon and echoed input via theme.
- cmd/root.go calls theme.ApplyOverride() in PersistentPreRun.

Detection adds no cost: because the command package imports Bubble Tea,
its init() already triggers (and caches) the terminal background query for
every command, so the non-TUI colorizers just read the cached value.
Terminals that don't answer the query fall back to the dark palette;
GH_STACK_THEME=light|dark forces it. Colors are truecolor on capable
terminals and downsample to the nearest ANSI color elsewhere.

Tests: internal/theme covers palette adaptiveness, ApplyOverride, the
colorizers, and FgSeqs; a new internal/config test verifies the wired-up
Config.Color* funcs adapt to the background when color is enabled.

Docs: README and the CLI reference note that GH_STACK_THEME now controls
all colored output, not just the interactive screens.

No behavior change beyond colors.
2026-06-29 20:11:09 -04:00
Sameen Karim bf2358bf12 trunk command (#108)
* Add `gh stack trunk` navigation command

Add a new navigation command that checks out the trunk branch of the
current stack.

The command is stack-aware: it requires the user to be on a branch that
is part of a stack, loads the stack metadata, and checks out `s.Trunk.Branch`.
If the user is already on the trunk branch, it prints a message and exits
without calling git checkout.

New files:
  - cmd/trunk.go: TrunkCmd (cobra command) + runTrunk implementation
  - cmd/trunk_test.go: 7 test cases covering happy path, already on
    trunk, from top of stack, not in a stack, checkout failure, custom
    trunk branch name, and positional argument rejection

Modified files:
  - cmd/root.go: register TrunkCmd in the "nav" command group
  - README.md: add `gh stack trunk` to the Navigation section
  - docs/src/content/docs/reference/cli.md: add `gh stack trunk`
    reference section

* address review comments

* increment skill version
2026-05-26 17:39:39 -04:00
Sameen Karim 00a9589feb rm merge command (#89) 2026-05-15 14:01:03 -04:00
Sameen Karim 8a9f1c86f8 commands help text (#88)
* more help text for commands

* improved root help

* fix typo

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* updated examples for add cmd

Co-authored-by: Sameen Karim <skarim@github.com>

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-15 14:01:02 -04:00
Sameen Karim 7a268fc380 modify command (#72)
* git primitives for modify cmd

* extract reusable TUI parts

* modify cmd

* recreate stack after modify

* add checks to prevent other modifications while modify is applying

* modify continue for resuming after resolving conflicts

* fix bug with duplicate stack entries after modifying

* reuse conflict resolution help msg from rebase

* additional confirmation before overwriting stack on remote

* fix recreate order of operations

Co-authored-by: Copilot <copilot@github.com>

* move base commit instead of cherry picking for fold up

* check to ensure we aren't left with zero branches

* unify and dedupe across view and modify tui

* more detailed help instructions

Co-authored-by: Copilot <copilot@github.com>

* only recommend submit if stack exists on remote

Co-authored-by: Copilot <copilot@github.com>

* tests for modify tui, apply modifications, submit modifications

* refactor submit for regular and pending modifications

* rename recover to abort

Co-authored-by: Copilot <copilot@github.com>

* docs for modify cmd

* tui styling updates

* updated tui screenshot

* addressing review comments

* Fix 4 bugs from code review

Bug 1: Move RevParseMap error check before using originalRefs.
The error from git.RevParseMap() was deferred past iteration of
originalRefs, which could panic on a nil map.

Bug 2: Differentiate cherry-pick vs rebase conflicts in modify.
Cherry-pick conflicts don't save state as 'conflict' phase, so
--continue won't work. Now prints --abort-only instructions for
cherry-pick conflicts.

Bug 3: Unwind now cleans up branches created by renames.
After restoring snapshot branches, Unwind deletes renamed branch
names that don't belong to the original snapshot.

Bug 4: Simplify push message in submit command.
Changed from 'Pushing N branches to remote...' to 'Pushing to
remote...' since individual branches may fail.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix 7 nit issues from code review

11: Add named constants for phase strings (PhaseApplying, PhaseConflict,
PhasePendingSubmit) in state.go; replace remaining raw literals in
state.go CheckStateGuard.

14: Fix bottomLines comment mismatch — listed 3 items but value is 2.

15: Extract magic number 88 to MinWidthForArt constant in header.go.

16: Remove unused stackview import anchor in model.go — the import
is used via types.go where BranchNode is embedded.

17: Simplify CheckStackLinearity parent resolution — ActiveBaseBranch
already handles skipping merged branches.

18: Fix rename undo matching any rename — add NewName check so only
the specific rename being undone is matched.

20: Add TestUndoRename and TestUndoRename_DoesNotAffectOtherRenames
to validate rename undo behavior.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Make cherry-pick conflicts recoverable via --continue

Previously, cherry-pick conflicts during fold-down operations could only
be resolved with --abort. Now they save full conflict state (phase,
conflict type, fold branch/target, remaining branches) to the state file,
enabling recovery via 'gh stack modify --continue'.

Changes:
- Add ConflictType field to StateFile (rebase or cherry_pick)
- Add FoldBranch/FoldTarget fields for cherry-pick context
- Add CherryPickContinue to git package (cherry-pick --continue)
- Save cherry-pick conflict state in ApplyPlan with remaining branches
- ContinueApply handles both rebase and cherry-pick conflicts
- Unified conflict messaging in cmd/modify.go (both types show --continue)
- Updated test to verify cherry-pick conflict state is saved correctly

* Apply suggestions from code review

Co-authored-by: Luke Ghenco <lukeghenco@github.com>
Co-authored-by: Sameen Karim <skarim@github.com>

---------

Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Luke Ghenco <lukeghenco@github.com>
2026-05-04 22:34:42 -04:00
Sameen Karim 7af17b55dc switch command (#51)
* switch cmd to interactively switch to another branch in the stack

* add switch to docs

* addressing review comments

* bump skill file version

* default to current branch
2026-04-20 11:20:27 -04:00
Sameen Karim a00ff54996 link command for api-only operations (#50)
* link cmd for api-only stack upserts

* accept branch names too

* push branches first

* update docs with link cmd details

* adding more logging
2026-04-20 11:19:01 -04:00
Sameen Karim b01754e4a9 Initial release 2026-04-10 03:32:08 -04:00