TurtleGit for Mac

View Markdown source ↗

Bisect progress, guarded review and owned continuations — October 18, 2026

Source pin 7338078f8ddd924b8cddee35f512f2286072136d: partial IDD_BISECTSTART and shared IDD_GITPROGRESS coverage, BisectStartDlg.cpp, AppUtils.cpp::BisectStart (3567) and BisectOperation (3647), and ProgressDlg.cpp completed progress (311 onward) and IDC_PROGRESS_BUTTON1/post-command list handling (406 onward).

Implemented connected family

The completed Bisect result now offers the source default action with an adjacent menu, replacing the separate horizontal classification buttons. When available, Submodule Update is first, followed by Good, Bad, Skip and Reset with their original update/thumb/Bisect artwork. A failed/interrupted active operation keeps only Reset. A successful Reset has no classification actions, while its optional Submodule Update remains available as in AppUtils. Existing custom good/bad terms, culprit display, actual Git state and original source command precedence remain.

Each actual progress attempt records elapsed time and completes at 100 with Success, User cancelled or the failure status. The existing completion formatter supplies the source-style status/date/elapsed footer, honors ShowGitexeTimings and the date locale preference, and marks the exact output completion range for native styling. Live streamed work/percentage remain unchanged. Read-only loading does not invent a successful command receipt. New attempts clear the old footer; Action log history retains the completed previous attempt. Forced retirement keeps the accepted display frozen rather than appending late completion text.

Start-field bindings and picker/Start/split-action callbacks carry a model/form epoch. Loading, progress transitions, picker ownership, Return to options, Quit confirmation and retirement invalidate prior controls. Guarding lives in the model binding so a deferred native combo notification cannot exploit a stale enabled view. Picker results still capture their original target/string and now also reject a changed owner epoch. All normal form, picker, cancellation and continuation dispatch is blocked while confirming application Quit. Root keeps that flag through both deferred termination paths.

Owned Log pickers, dirty-worktree Stash/Abort questions and kill confirmations inherit the captured owner's alpha and appearance before presentation. Picker preferences remain the actual Bisect owner's private/captured preferences. A Submodule Update continuation is captured once, closes the Bisect owner, waits for actual AppKit sheet detachment, releases ownership, then invokes the captured follow-up. The child-release counter blocks Quit during that interval. Root uses the same preferences for the resulting Update dialog.

Mutation receipts and compatibility

startBisectWorkflow, bisectWorkflow and stashBeforeBisectWorkflow return actual results plus typed BisectMutationResult receipts. Receipts retain the kind, attempted commands, statuses, complete original output and cancellation. An exception after a successful earlier command or during a later command throws BisectMutationFailure, retaining both the receipt and underlying error. The old Start/classification/Stash APIs preserve their original return/error contracts by delegating and unwrapping the underlying error. Canonical object queries read stdout and remove only Git's final LF; successful ambiguity warnings on stderr cannot enter a subsequent Good/Bad argument. Git-directory queries retain their existing exact stdout/single-LF path handling. Validation failures before mutation still return their original failures.

Native onAttemptCompleted publishes an attempted receipt once, even if its owner was force-closed while Git was running. Root uses it to refresh repository history, Commit, Status and replay state. These refresh facts are distinct from a successful complete operation: a failed command or post-command metadata read may follow partial ref/index/working-tree changes. Legacy onChanged remains live-only for existing consumers and observed Logs; it is not a success callback. No late view or legacy callback is revived after retirement.

Stash retains its existing backend unchanged. Its receipt conservatively covers the submitted save operation, including internal save/preflight/post-save reads; it does not claim every thrown save reached Git or created a new stash. A receipt whose submitted commands exited zero does not prove a subsequent state/metadata read succeeded. There is no automatic rollback or stash reapply.

Grouped verification

The Debug app build and 23 selected Reset/Bisect Core cases pass. The new Bisect native operation case passes with system and bundled Git. The grouped checkpoint records retained coverage, actual failures, affected rechecks and process cleanup.

These scoped checks do not establish physical theme/layout/keyboard/VoiceOver acceptance, every checkout hook, signed Finder/App Store or complete hosted CI. Owned test windows and children are closed and operation/release counters drained on success/failure. No user clipboard or public server is used.

Remaining adaptations and limits

The native review and progress remain one owned window; upstream creates separate modal instances. Dirty-worktree approval remains at accepted Start rather than before opening the review. The native backend validates supplied commits before mutation and stops Start after a nonzero step; upstream's generic command-list runner can continue after an ordinary error. Existing safety behavior is retained rather than sending later classification commands after a failed Start.

Custom terms, merge/replay exclusions, tracked-only Stash, untracked checkout protection, linked-worktree paths and source command precedence are preserved. An external process can change Git state between queries and mutations. There is no transaction-wide rollback, automatic stash apply or guarantee of successful completion merely from displayed controls. Physical split-menu/default-button behavior, full progress visual parity, real diagnostics/accessibility acceptance, all partial metadata-read failures and signed deployment remain open. This is a partial Bisect family replacement, not certification of the entire port.