Skip to content

various tix improvements - #2938

Draft
Sebastian Thiel (Byron) wants to merge 100 commits into
mainfrom
tix-improvements
Draft

various tix improvements#2938
Sebastian Thiel (Byron) wants to merge 100 commits into
mainfrom
tix-improvements

Conversation

@Byron

Copy link
Copy Markdown
Member

Tasks

  • ensure all changes to non-tix are separately reviewed before merging

@Byron
Sebastian Thiel (Byron) force-pushed the tix-improvements branch 7 times, most recently from 9435460 to 6b0ae90 Compare August 28, 2026 09:37
@Byron
Sebastian Thiel (Byron) force-pushed the tix-improvements branch 11 times, most recently from 14d64e9 to 9fa9982 Compare September 8, 2026 05:41
History previously used the absence of view tips as a proxy for empty visible
history. A newly created branch at, or behind, a hidden branch still has a view
tip, so traversal and projection discarded every row and left no selection for
creating the first stack commit or opening a rebase.

Keep current view tips as hidden boundaries when exclusion removes all visible
commits, while retaining the hidden-tip fallback for unborn HEAD. Treat a
boundary with zero visible descendants as an editable empty stack, and carry
refs from the old base into an empty rebase-update so saving the unchanged todo
advances the branch.
The history copy action always emitted the selected commit's object ID, even while the view showed its change ID.

Choose the clipboard effect from the effective ID display mode. Hidden and commit-ID modes retain object hashes, while change-ID mode writes the full reverse-hex change ID.
Review departure pins were indistinguishable from ordinary user pins. When a rewrite moved one onto a later checkout destination, normal time travel could consume it before the review finished and force detached fallback selection.

Give each review an explicitly owned pins/review/N return ref, keep generic travel and pin actions away from those refs, and consume the exact ref only when finishing or cancelling its review. Cover the squash-and-finish lifecycle and document the ownership contract.
Add a View Select command and v c shortcut that collect a displayed #N through the existing notice area. Resolve the number relative to the selected row's visual root so duplicate entry numbers in disconnected history trees cannot move the cursor across trees.

Keep invalid input editable, support pasted entry numbers, and document and test the interaction.
Ordinary pins at attached HEAD were filtered out together with the inactive HEAD return pin. When HEAD was displayed as an otherwise-empty hidden boundary, the missing decoration made the action menu call an existing pin "pin" instead of offering "unpin".

Keep ordinary pins applicable at attached HEAD while continuing to exclude the special HEAD pin. The existing tip deduplication prevents any traversal change, and a regression covers the hidden-boundary decoration that drives the unpin action.
Pending-rebase validation followed the parent of a checked-out review commit and mistook the review’s lazy base for a pending checkout path. Stop validation at the edited review boundary so staged changes can amend the active review while preserving ordinary pending-path protection.

Add regression coverage for a review commit whose parent carries tix-rebase-parent, and document the boundary behavior.
Checkout-path validation followed raw first-parent ancestry beyond the hidden base, so historical tix-rebase-parent markers could block edits in an otherwise final visible stack.

Limit pending validation to commits stored in the active history graph and give command-line HEAD edits the same inferred hidden base as the history view. Cover both reword and index-only amend against pending history below that boundary.
Pending checkout validation derived its boundary from commits cached or rendered in a HistoryGraph, while commands selected inconsistent graph loaders. This could reject edits because of hidden pending ancestry or skip checks for frozen rebase plans.

Track the active edit scope explicitly, share visible-boundary calculation with the UI, validate plans against their declared scope, and model pending HEAD finalization as an explicit policy.
Make J/K traverse every displayed parent and child edge. When a node has multiple destinations, keep the cursor at the source and let h/l choose the numbered destination before Enter confirms it or Escape cancels.

Use the same temporary choice interaction in the ref-tree, remove persistent child memory and lane emphasis, and discard choices whenever asynchronous lane computation replaces their indexed graph.
Prepare the review reference, return pin, and synthetic commit before attempting to activate the review checkout. Dirty worktrees can now proceed when Git accepts them, while a blocked checkout leaves the prepared review intact and reports its full commit ID.

Avoid forced rollback after checkout failures so local worktree changes cannot be discarded. Keep the finish-time cleanliness check and cover the partial-success path with a regression test.
Let active review commits use the same index-first, worktree-fallback amend behavior as ordinary HEAD commits. This makes a freshly started review amendable without requiring the reviewed delta to be staged first, including from a focused unstaged path.

Keep review identity, return ownership, pending-boundary handling, and index-only CLI behavior intact.
Make copy-insert available whenever move-insert is available, including when HEAD is an active review commit.

Strip review identity and return ownership from the copied occurrence so the retained source remains the sole owner of its review resources. Reuse the same identity removal when finishing reviews.
Outside the actions prefix, `Shift-P` decoded as comparison-parent cycling,
which did nothing in history. Make it push the active branch directly from
history or the Worktree pane, regardless of the open prefix menu. Accept both
uppercase `P` and terminals reporting lowercase `p` with Shift.

Keep comparison-parent cycling local to the focused Tree pane, where
`a Shift-P` still explicitly pushes. The command popup continues to consume
`p` and `Shift-P` as query text, even when a push is available.

Update `spec.md` and regression coverage for prefix-independent pushing,
Tree's local shortcut, and command-popup input. All 557 tests, formatting,
and Clippy pass, and the debug executable builds successfully.
Existing commit-message editors showed the message and identities without
any summary of the underlying patch. New-commit editors already provided
per-path churn, signed net line counts, and aggregate totals.

Reuse that summary writer for both the TUI and command-line reword documents.
Compare the selected commit's tree with its first parent, or the empty tree
for a root. Pending rebases retain their recorded comparison parent so the
summary describes the original patch independently of the current checkout.

Keep the summary in comments that are stripped from the saved message, using
the display formatter to keep filenames containing line breaks on one line.
Update `spec.md` and cover committed line counts, root and merge comparisons,
pending rebases, and message preservation in regression tests.
Local branch labels were less prominent than remote-tracking labels in the
history view. The different colors also made branch kinds visually compete
when their shared role as branch names was more useful.

Render local, remote-tracking, checked-out, and remembered branch labels in
the existing remote-branch yellow. Apply the override where history labels
are rendered so the reference tree keeps its own palette. Retain tag colors
and annotated-tag emphasis, detached-worktree colors, and branch markers.

Update `spec.md` and the existing rendering checks for branch colors,
worktree labels, and both tag styles.
A reference-tree pin could be created successfully yet disappear on return to history: hidden view tips were retained only when the entire view was empty. The same filter lost existing pins on startup.

Keep each hidden view tip as a selectable boundary alongside visible stacks, without exposing its ancestry. Apply the rule to initial loading and the shared display/edit scope, and cover pin refresh selection and reloading symbolic pins.
History reports hidden branches at their shared base and upstream
relationships at local branch tips, but those indicators did not provide a
way to bring the related history into the view.

Add View → show related history (`v o`) to collect all matching hidden
branches or unnamed tips and the selected branches' configured upstreams.
Resolve upstream names through fetch refspecs and deduplicate by reference
identity so distinct branches remain selectable. Pin immediately for one
target; reuse the command menu's searchable picker and Escape handling for
multiple targets. Report when there are no related targets.

Create or reuse ordinary pins and select the target after refresh. References
remain symbolic and are resolved again when chosen; unnamed commits use fixed
pins. Pinning hidden history now shows the commits connecting the tip to the
shared base with the existing dim, read-only boundary styling. The shared
visibility calculation handles both cached refreshes and initial loading,
while older shared ancestry remains hidden, including across merge parents.
Only moved reference decorations may redirect refresh selection, so an
unchanged branch cannot override the chosen pin target.

The normal pin undo log and persistence apply. Derive visibility from current
view tips so restarting preserves the revealed range and unpinning hides any
rows no remaining tip needs. The checkout stays unchanged, and there is no
separate state specific to the related-history action.

Validation: all 568 `gix-tix` tests with all features, formatting, Clippy,
and an all-features build pass. Live PTY checks cover direct and multiple
targets, remote upstreams, persisted visibility, unpinning, cancellation,
and unchanged checkout and older-history exclusions.
Keep a checkout composed from named branches and pins without turning their
merge into an obstacle to editing or rebasing its inputs. Store ordered ref
subscriptions in `tix-auto-merge` commit headers and resolve them again when
inputs change, on travel, or through an explicit remerge. Initial creation
preserves source refs and checks out the derived commit detached.

Merge inputs in order, retaining a conflicting tip as a parent while muting
its entire tree contribution. Exclude muted inputs from intermediate merge
ancestry so later inputs can still contribute. Generate titles such as
`✔️ A 💥 B ✔️ 📌`, prune disappeared refs, preserve distinct subscriptions
when tips converge, and collapse a single remaining subscription to its tip.

Reuse the command popup's fuzzy picker for `aM` and input removal. Prefer local
branches, then pins, remote branches, and commit tags. `aU` refreshes the
selected AutoMerge HEAD; `ax` removes a selected input and disambiguates its
memberships; `aX` chooses an input from the selected AutoMerge. Preserve input
refs, including subscribed pins which checkout cleanup would otherwise consume.

Maintain derived commits throughout the current editable projection using the
existing transactional edit and lazy replay machinery. Pending inputs replay
independently; conflicting optional replays retain their original patch and
stay muted. Rebase todos use ordinary `pick` lines and resolve subscriptions
from final ref placements across fork sections. Review finishing and branch
attachment also update dependent merges. Keep generated trees and titles out
of direct editing while allowing ordinary descendants and enrichments.

Group ref changes and checkout in undo, verify input refs at publication, and
retain only detached AutoMerge metadata while the UI is idle. Watchers remain
read-only. Document the behavior in `gix-tix/spec.md` and cover conflict muting,
replay, external resets, pruning, nested dependencies, todo continuation,
review finishing, attachment, concurrent changes, picker actions, and undo.

Validation: all 583 Tix tests pass with `sha1,sha256`; crate Clippy passes with
`sha1,sha256,blocking-network-client`; formatting passes. A terminal smoke test
exercises creation, fuzzy selection, muted inputs, adding and removing inputs,
and explicit refresh after an external branch advance.
`ExpectedRef` mixed observed state with three overlapping descriptions of
where a reference would end up. In particular, an absent new object ID could
mean either deletion or a step that had not run yet, which made AutoMerge
ordering and literal existing-commit destinations error-prone.

Replace it with `PlanRef` and an explicit `RefDestination`. Resolve automatic
following before execution, and share the result with checkout inference and
AutoMerge dependencies. Keep the observed ref value and logical todo origin
separate so conflict continuations retain their compare-and-swap checks.
Remove the duplicate following calculations and per-merge ref-vector clones.

An unproduced input is now rejected instead of silently being pruned. Existing
reference-placement, continuation, and linked-worktree regressions still pass.

Validation: all 583 `gix-tix` tests with `sha1,sha256`; the strengthened
AutoMerge input-destination regression; Clippy with the network feature;
`cargo fmt` and `git diff --check`.
Edits, review completion, and rebase todos planned different operations but
also carried separate implementations of AutoMerge rebuilding, optional
conflict handling, signature invalidation, and signing progress. A correction
to one execution path could easily leave another behind.

Use one bounded `Replay` executor for applying trees and parents, preserving
optional conflicting inputs, rebuilding derived commits, and writing commits
with their change IDs, replay markers, and signatures. Keep the distinct
planning and squash/continuation rules at their callers. AutoMerge cycle
validation now also runs when a review completes.

The refactor removes 98 implementation lines without a new generalized plan
format or dependency. The existing end-to-end regressions exercise all three
callers, including optional conflicts, continuations, notes, and signing.

Validation: all 583 `gix-tix` tests with `sha1,sha256`; Clippy with the network
feature; `cargo fmt` and `git diff --check`.
The history cache already recorded whether a commit had been loaded, but
`parents_of()` returned an empty parent list for an interned frontier. This
made an external AutoMerge input look like a root and required an AutoMerge-
specific workaround that equated edit scope with cache completeness.

Honor the existing loaded bit and move read-through ancestry lookup into
`HistoryGraph`. Name traversal-only cached edges `known_parents` and limit
descendant rewrites to the explicit edit scope. Looking up missing ancestry
neither populates the cache nor expands permission to edit it.

Extend the exact-scope regression to distinguish unloaded frontiers, loaded
roots, and ancestry reads. It failed with `Some([])` before the fix and now
passes, together with the external-input replay regressions.

Validation: all 583 `gix-tix` tests with `sha1,sha256`; Clippy with the network
feature; `cargo fmt` and `git diff --check`.
`Complete` previously described reference publication even when callers still
had to check out the result, clean up pins, and delete a departed branch. Every
caller handled that second phase separately, and failed checkout could leave a
successful rewrite without its requested working tree.

Move these steps and accepted conflict materialization into the bounded replay
operation. Return their combined reference changes for undo, share worktree
rollback with the undo executor, and preserve index bytes on checkout failure.
A post-checkout hook error after Git reaches the destination remains a warning
with the completed move recorded. Remove the intermediate persisted-conflict
state and the duplicated checkout handling in the CLI and TUI.

Regression coverage exercises a locked `HEAD` during checkout, completed
checkout with a failing hook, and deferred branch deletion in undo changes.
All 585 Tix tests pass with both hash features, along with formatting and Clippy
with the blocking network feature enabled.
AutoMerge commits record the input IDs they actually merge. A concurrent
change to an input ref leaves that result valid and can be picked up by the
next remerge, so locking inputs through publication adds complexity without
keeping merges current after the operation ends.

Remove input verification from prepared rewrites and use cached input states
only while resolving merges. Resolve todo inputs from their planned
destinations; expected-value checks remain on refs the operation writes.
Unchanged inputs stay out of undo history and retain their reflogs.

The regression advances an input during merge creation, checks the recorded
parents and recipe against the checked-out snapshot, and verifies that the
next remerge includes the advance. Packed-input coverage remains, and the
existing stale-writer regression continues to protect output transactions.
Grouped command keys and actions were specified twice: once while assembling
menu entries and again in the keyboard decoder. Each AutoMerge action therefore
needed another switch arm, and shifted letters could take different routes
depending on their terminal encoding.

Declare each command's group, shortcut, and action once. Menu construction keeps
its existing labels and availability rules while obtaining bindings from that
catalog; grouped keyboard dispatch consults the same bindings. Keep navigation,
prefix switching, and direct keys explicit, and normalize shifted characters
before lookup. Control paging and the undo/redo repeat guard retain precedence.

The new shifted-encoding regression fails with the former decoder and passes
for every group with the shared lookup. All 586 Tix tests pass normally and all
591 pass with networking enabled, along with formatting and Clippy. This task
removes 278 lines including its regression and specification update.
AutoMerge previously required a named input and an unambiguous branch or pin
at HEAD. Allow selected commits outside HEAD's ancestry to be merged into
HEAD, preferring local branches and ordinary pins through the existing fuzzy
picker and falling back to effective change IDs. An unnamed or ambiguously
named HEAD uses the same fallback. Merge parents retain unnamed inputs
without creating tracking refs or pins.

Track logical rewrites separately from ref movement so change inputs follow
retained commits through edits and todos without following inserted children
or copies. Dropped inputs and inputs squashed into a different identity lose
their subscription. Exact edits take precedence during both dependency
discovery and replay, including inputs outside the lookup projection.

Resolve change IDs lazily within the active history only when hidden tips
bound it. Keep missing or ambiguous inputs at their recorded version, report
ambiguity, and never choose a version by timestamp. Preserve this boundary
when expanding replay graphs, and carry diagnostics through UI and CLI
completion paths with CLI notices on stderr.

Reuse AutoMerge's metadata, removal picker, muting, nested replay, checkout,
signing, and undo machinery. Update `gix-tix/spec.md` and cover selection,
metadata, bounded resolution, exact placements, insert/split/copy/drop/squash,
nested conflicts, multiple memberships, and undo.

Validation:
- `cargo test -q -p gix-tix --features sha1,sha256` (595 tests).
- `cargo test -q -p gix-tix --features sha1,sha256,blocking-network-client`
  (600 tests).
- `cargo fmt --all -- --check`.
- `cargo clippy -q -p gix-tix --all-targets --no-deps --features sha1,sha256,blocking-network-client -- -D warnings`.
Worktree paths could be amended, but discarding an unwanted edit required
leaving `tix`. Add `Actions discard` to the command picker and reuse `a d` for
the focused Worktree path. History keeps `forget`. Share action visibility
between the picker, popup, and footer so discard also works when the selected
history entry cannot be amended.

Use Git with literal pathspecs to restore unstaged edits from the index and
reset staged or conflicted paths in both the index and worktree to `HEAD`.
Remove untracked and intent-to-add files, restore rename sources, and support
an unborn `HEAD`. Revalidate the selected change before acting, reject
unsupported submodules, and preserve unrelated paths and history. Close the
actions group after discard so a repeated key cannot discard the next path.

Update `spec.md` and cover menu routing, rendering, staged and unstaged edits,
additions, renames, conflicts, literal filenames, stale selections, and index
locks. All 602 tests pass with `sha1,sha256`, and all 607 pass with
`blocking-network-client` as well. Formatting and scoped Clippy checks pass.
Several Actions labels repeated their shortcut before the verb, while others
used letters absent from the verb. Make every action underline its key inside
the verb, using the key's case in labels such as `New-empty`, `Split`, `Fetch`,
`Push`, and `AutoMerge`. The command picker shares these labels and retains
case-insensitive search.

Rename `forget` to `delete` throughout the action, notices, undo descriptions,
and editing module. Describe AutoMerge input removal as `exclude from
AutoMerge` and `eXclude input` so its existing `x` and `X` keys are embedded.

BREAKING CHANGE: Stash and unstash move from `a z` to `a Shift-T`, displayed as
`sTash` and `unsTash`. Remerge moves from `a Shift-U` to `a Shift-R`, displayed
as `Remerge`.

Update `spec.md` and the existing menu, keyboard, rendering, and deletion
coverage. All 602 tests pass with `sha1,sha256`, and all 607 pass with
`blocking-network-client` as well. Formatting and scoped Clippy checks pass.
Spinning off an experiment previously required a local branch. Add
`tix wt switch --detach [COMMIT]` (`-d`) to create a linked worktree at
the current physical `HEAD` or a supplied commit revision. Keep the
existing `--path` override and shell handoff, and choose numbered sibling
paths when multiple experiments start at the same commit.

When the source worktree already has valid Tix pins, create an ordinary
symbolic pin there targeting `worktrees/<id>/HEAD`. Reuse the shared pin
helper so external commits and checkouts stay visible in the source's
history. The source pin is the entire parent/offspring relationship; the
new worktree starts unpinned and no branch is created.

Document the command and cover creation, protected destinations, invalid
and unborn targets, physical versus remembered HEAD, and pin privacy and
following from both main and linked source worktrees. Validate with all
611 Tix tests, scoped Clippy, formatting, and CLI smoke checks in SHA-1 and
SHA-256 repositories, including shell handoff and bare-repository creation.
Showing configured hidden ancestry required the `v h` sequence or the
command menu. Route `Shift-H` through the existing hidden-history action
from history and both changes panes, including with a shortcut group open.
Ordinary `h` and Shift-Left retain horizontal navigation; modal pickers keep
consuming shortcut letters as input.

Document the direct hidden-history and push shortcuts in `?` help and a
README keyboard section linked to the full specification. Embed the capital
shortcut letters in the displayed verbs, following the existing action style.
Cover terminal key encodings, both toggle directions, focused panes, prefix
groups, command-menu input, and rendered help. All 612 Tix tests pass.
The status line repeated the `p command` hint already available under `?`.
Remove that duplicate to leave more room for contextual status and shortcuts.
Adjust the shared prefix-popup anchor calculation so the expanded groups
remain attached to their labels on the shorter footer.

Keep `p command` in the information popup. Update the footer render fixtures
and specification; the existing help and popup-alignment checks cover both
its continued discoverability and the new layout.
Picker selections opened another Tix session before the shell wrapper could
apply its directory handoff. The terminal emulator therefore kept reporting
the source directory while the selected worktree's history was open.

Return picker selections through the same path handoff as explicit switch
targets. The wrapper can change directory and run the shell's normal CWD
hooks before the user opens Tix again. Without shell integration, print the
selected path and exit.

When Tix starts without `-x`, infer integration branches through the remote
`HEAD` mappings already used by `tix show`. Start with full history and offer
one reversible display control: `hide unrelated history` applies those
exclusions, and `show related history` restores the full ancestry of the same
view tips. Both directions use `Shift-H` or `v h`. Explicit filters apply
immediately and are not broadened by inference.

Remove the separate related-target picker, its pinning action, and its `v o`
shortcut. Showing or hiding history now only changes the view, preserving
existing pins and undo history. Ordinary explicit pinning remains available.

Update `spec.md`, the README, and regression coverage for inferred, explicit,
missing, and invalid filters and the single contextual history command. All
608 Tix tests pass with `sha1,blocking-network-client`. Pseudo-terminal checks
cover picker selection and cancellation, path output, the shell's CWD hook,
both live toggle directions, existing pins, and unavailable inference.
Selected history rows invert their field colors, so the blue date background
previously ran straight into the author background. Render the date's existing
trailing space with the row's default colors to preserve the margin without
moving any metadata columns.

Update the selected-row buffer and palette expectations and document the
spacing in `spec.md`.

Validation: all 608 `gix-tix` tests, crate-scoped Clippy, and formatting checks
pass.
A failed `git stash apply --index` previously deleted the Tix reference
unconditionally. A conflict in `Cargo.lock` could stop Git before other
files were restored, leaving the saved index, worktree, and untracked
state unreachable through Tix.

Delete the reference only after Git succeeds, retaining the existing
expected-target check. Report that the complete stash remains available
on any failed apply. This shared path protects both manual commit
stashes and review auto-stashes, including restoration during time
travel. Partial index and worktree changes remain available for
inspection or conflict resolution.

Match `git stash pop`, which retains its entry when application fails.
Add a regression for an early index conflict followed by a successful
retry of all staged, unstaged, and untracked files. Update the review
regression to retain saved state after merge conflicts and index-lock
failures, and synchronize `spec.md`.

Validation:
- Confirmed both regressions fail before the fix with missing stash refs.
- All 604 `gix-tix` tests pass with `sha1`, isolated Git configuration,
  `GIX_TEST_IGNORE_ARCHIVES=1`, and macOS watcher access.
- `cargo fmt --all -- --check`
- `cargo clippy --locked --offline -p gix-tix --features sha1
  --all-targets -- -D warnings -A unknown-lints --no-deps`
Rewording an ancestor used to mark off-checkout descendants for lazy replay
even when neither their tree nor their parent trees changed. Besides making
time travel do unnecessary work, that made content-derived metadata appear
stale after edits that only changed commit headers.

Share the final-state decision across ordinary edits, review completion, todo
replay, and AutoMerge. A previously final commit can be reparented and signed
immediately when its result and ordered parent trees are unchanged and its
new parents are final. AutoMerge also preserves its ordered recipe and muted
inputs. Existing pending commits and conflict-dependent writes remain lazy.

Add regressions for off-checkout descendants, configured signatures, nested
AutoMerges, and undo/redo. Adapt replay tests to use actual content changes
when pending history is required, and synchronize `gix-tix/spec.md`.

Validation:
- Both new reword regressions fail before the fix and pass afterward.
- All 606 `gix-tix` tests pass with `sha1`, isolated Git configuration,
  `GIX_TEST_IGNORE_ARCHIVES=1`, and native macOS watcher access.
- `cargo fmt -p gix-tix -- --check`
- Crate clippy with all targets passes (an existing removed-lint warning remains).
Tree-based review marks disappear when an ancestor changes unrelated content.
Attach explicit refactor/review approval to a version of a Tix change's patch,
so the same edits retain their approval across rewording and replay even when
context, line numbers, or hunk grouping change.

Store a versioned `patch-id` commit header with a `ghij`-encoded fingerprint
and its base/result tree witnesses. Hash raw changed paths, modes, and bytes
with a fixed Histogram diff; preserve whitespace and newline distinctions.
Reuse matching tree witnesses or changed-leaf records before reading blobs.
Lazy rewrites keep stale IDs without computing patches. Conflict placeholders
remain unavailable until explicit resolution, including when retained as
muted AutoMerge inputs.

Store `refackiewed` notes per change ID and patch version under the worktree's
`refs/worktree/tix/enrich-patch`. Add `n r` and
`tix enrich patch refackiewed [--clear] [REVSPEC]`, and display `✨` alongside
the existing enrichments in the TUI, `show`, and rebase todos. Legacy marking
publishes its header, approval, and descendant ref rewrites atomically with
one undo operation, preserving staging and worktree bytes. Existing identities
need only a notes update. Keep tree checks independent.

Browsing reads existing metadata only. Explicit fingerprinting uses the
existing mutation worker and progress display. Preserve unchanged AutoMerge
header order so no-op remerges retain commit IDs, and seed identities on new
AutoMerges even when their first-parent delta is empty. Document the identity,
eligibility, lifecycle, and performance rules in `spec.md` and `README.md`.

Validation:
- Regression coverage for normalized patch identity, fast reuse, lazy replay,
  conflict resolution, AutoMerge, atomic approval/undo, staging, and display.
- All 626 `gix-tix` tests pass with `sha1` and with `sha1,sha256`, isolated Git
  configuration, `GIX_TEST_IGNORE_ARCHIVES=1`, and native macOS watcher access.
- A real SHA-256 repository passes CLI mark/show/clear with a 128-character
  patch ID, matching tree witnesses, and a clean worktree.
- `cargo fmt -p gix-tix -- --check`
- Crate clippy with both hash features and all targets passes (an existing
  removed-lint warning remains).
Explicit history rebases previously left Git `fixup!`, `squash!`, and
`amend!` commits as ordinary picks. Manually squashing a correction also
retained its commentary, so fixups could not preserve or replace the
target message.

Recognize markers during initial CLI and TUI todo preparation, using
Git subject/name/prefix matching and linked fold ordering within editable
first-parent ancestry. Preserve intervening commits, fork topology, tip
references, and checkout when moving corrections beside their targets.
Generated actions remain editable, and accepting an unchanged autosquash
todo applies it without changing implicit edit or travel replays.

Carry append, discard, and replace modes through replay and continuation.
Keep Tix squash messages and authorship conventions, support `fixup` and
`fixup -C`, and preserve target identity and notes. Remove consumed review
resources even when a fold conflicts, and omit those deleted resources
from continuation expectations.

Document the behavior and intentional Git differences in `spec.md` and
todo help. Add Git-oracle, matching, ordering, topology, message, identity,
and conflict-continuation regressions using the existing fixtures.

Validation: all 619 `gix-tix` tests pass with `sha1,sha256`; formatting and
crate Clippy checks pass. The complete test run isolates global/system
Git configuration and runs outside the sandbox for macOS event delivery.
Pending `fixup!`, `squash!`, and `amend!` commits will be folded during
explicit rebases, but their titles previously looked like ordinary text.
Show distinct bold, underlined light-magenta symbols before the target
title so these commits stand out beyond conventional commit types.

Reuse the rebase marker parser, including nested-prefix handling, and
retain conventional formatting and Markdown within the target. Keep
badges when history titles are shortened and preserve existing HEAD,
selection, and hidden-boundary styling. Plain output and message panes
retain the original titles.

Validation: all 64 UI tests pass with `sha1,sha256`, as do `cargo fmt`
and `cargo clippy` for all `gix-tix` targets. The regression checks fail
without the implementation.
The UI rejected every merge commit before the existing deletion machinery
could handle AutoMerges. Allow generated merges through the same command while
retaining the restrictions on ordinary merges and their descendants.

Deleting an AutoMerge returns to its first parent only when it is checked out.
When `HEAD` is already below the merge, keep its symbolic state, index and
worktree untouched without a checkout-target prompt. Preserve input branches
and reparent descendants with their existing lazy replay behavior.

Cover command availability, deletion at and above `HEAD`, staged and unstaged
content, and descendant reparenting. Update the behavioral specification.

Validation: deletion regressions, app and command-menu tests, formatting, and
Clippy with both `sha1` and `sha256` enabled passed.
AutoMerge titles could leave conflict markers visually detached from their
inputs, especially when several pins appeared as identical symbols. Group each
status with its input label, such as `[✔️ A] [💥 📌] [✔️ 📌]`, and generate an
ordered bullet list explaining every contribution in the commit body.

The legend names full references and change IDs, including each pin's identity
and symbolic target. Muted inputs explain that conflicts or pending replay
exclude their entire contribution. Stable identities and the existing reference
snapshots avoid message churn after input rewords and add no display-time reads.

Eager rebuilds replace the generated legend while preserving other body text;
lazy rebuilds retain their message until replay. Keep unchanged remerges
idempotent and preserve legacy custom prose that uses the same section heading.

Update the behavioral specification and cover grouped conflict symbols, real
worktree HEAD pins, converged pin targets, full change identities, body
preservation, and legend updates when inputs change or disappear.

Validation: all 646 `gix-tix` tests with `sha1,sha256`, workspace formatting, and
Clippy for all crate targets passed.
Detached worktree creation only installed a source pin when the source
already had valid Tix pins. An ordinary attached source could therefore
create an experiment whose later commits disappeared from its history.

Always create the source-local symbolic pin when a source worktree exists.
The existing `worktrees/<id>/HEAD` target follows external commits and
branch checkouts without additional reference or watcher machinery. Bare
sources remain unpinned, and newly created worktrees receive no pins.

Extend the existing regressions to cover main and linked sources with
attached or detached HEADs, with and without prior pins, and child branch
checkouts. Verify that children starting at the same commit have distinct
tracking targets, and update the README and behavioral specification.

Validation: all 606 Tix tests pass with `sha1,sha256`, scoped Clippy passes,
and workspace formatting checks pass. Tests use isolated Git configuration
and native macOS filesystem notifications for the watcher check.
CLI smoke checks pass for SHA-1 and SHA-256 repositories, including
external HEAD advances, source pin privacy, invalid targets, and bare sources.
The reference tree listed detached worktrees at their physical HEADs, but
Enter and `p` ignored those labels. Experiments discovered in the overview
could not be retained in the current worktree's history through that action.

Include foreign detached worktrees in the existing reference-pin action.
Worktree snapshots retain their qualified physical HEAD reference separately
from the displayed or remembered branch. Fresh discovery matches the selected
commit, then the existing symbolic pin, undo, and history-refresh paths handle
the action. Pins follow later commits and branch checkouts outside Tix.

Main and linked worktrees retain distinct identities, including linked
worktrees named `main` or sharing the same commit. Repeated pinning reuses
each target. Existing attached-branch and current-detached-marker behavior
is unchanged, and stale selections cannot pin a worktree that moved away.

Cover keyboard dispatch, physical versus remembered HEAD, source pin privacy,
external changes, pin reuse, and qualified identities. Update the behavioral
specification with the new reference-tree action.

Validation: all 608 Tix tests pass with `sha1,sha256`; scoped Clippy and
workspace formatting checks pass. The new regressions fail without the
pinning change and pass with it.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants