TurtleGit for Mac

View Markdown source ↗

Git LFS locking parity

TurtleGit has a native LFS Locks… command in its app menu for the current working repository. It opens a resizable list with checkboxes, Path, Extension and LFS Lock owner columns. Select/deselect all, Force, Unlock, Cancel, Help and Refresh/F5 follow the upstream Locks dialog's main workflow. Highlighting and checked targets are separate. Sorting the list retains checked lock IDs.

Unlock opens an owned AppKit progress sheet with per-file paths, results and output. The controller explicitly attaches and closes its child window; SwiftUI renders the sheet contents. Individual failures do not prevent subsequent files from being processed. A failed unlock offers Force unlock with the captured original target paths, matching the upstream post-action. Closing the result dialog refreshes the lock list, including after cancellation or a failed operation. A refresh failure clears stale rows and retains the operation results. Force is explicit; it is never enabled automatically after failure.

Busy and Quit confirmation block target/force changes and duplicate actions. Closing a busy window requests cancellation and waits for completion; app Quit is refused while a request or result sheet is active. Cancellation retains completed results and does not imply that remote changes were rolled back.

The repository actor uses literal argument arrays for git lfs locks --json, git lfs lock -- <path> and git lfs unlock [--force] -- <path>. Every batch target is checked before the first LFS request; folders, escaping paths and repository administration paths are rejected. Individual command errors are returned with the corresponding file. Query parsing expects the CLI's JSON array, skips empty IDs and reports malformed records rather than interpreting the HTTP API envelope as CLI output. The common Git administration directory is used for the local LFS marker, including linked worktrees.

Command semantics were checked against the official locks, lock and unlock documentation. Port mapping uses pinned TortoiseGit 7338078f8ddd924b8cddee35f512f2286072136d: TGitPath.cpp, LFSLocksDlg.cpp/.h, Commands/LFSCommands.cpp/.h and ProgressCommands/LFSSetLockedProgressCommand.cpp/.h. Original lock/unlock artwork is reused; native owned sheets replace Windows modal progress.

Verification and remaining work

LFS QA record records private Core command fixtures, native window/table/sheet checks and build results. Core fixtures launch a private command wrapper that logs exact arguments and delegates ordinary Git commands to real Git. The wrapper supplies LFS responses; no server is contacted. Native workflow checks inject server replies and mixed results, verify force retry, cancellation, owner and operation guards, and preserve real repository HEAD/index/working contents. They do not verify a real Git LFS helper, authenticated remote or physical input.

The packaged Git engine includes Git LFS 3.8.0. Configuration/GitLFSRuntime.json pins both official publisher archives, the complete source archive, Go notices and all 28 external module archives/notices. Preparation verifies publisher SHA-256 checksums and Go module sums; auditing compares executable code/data and loader commands with publisher binaries even after replacement signatures. App Store embedding requires this helper and has no external Git fallback.

A real bundled-client loopback fixture verifies LFS pointer conversion, JSON lock listing, literal unusual filenames, ownership failures, continued per-file unlock and explicit force. It preserves HEAD, staged entries and working bytes. This complements the injected native dialog tests above. It does not establish authenticated provider or signed sandbox acceptance. See the runtime QA record.

Commit and Working Tree now offer original-icon LFS Lock/Unlock context actions when the repository has a common-directory LFS marker and the selection contains files without conflicts. With the owner column hidden, both actions match upstream AppendLocksMenuItems. Their captured selections run in a native sheet attached to the originating dialog; the owner stays busy through result review. Cancellation retains completed changes, failed unlock offers explicit Force retry against the original paths, and closing results refreshes the owner. No remote locks query is made to build this hidden-owner-column menu or refresh its local file rows. The standalone Locks window continues to refresh remote lock ownership. Working Tree joins the global Quit-confirmation guard; Commit and Working Tree refuse new LFS actions while busy or deciding whether to quit. The hidden native receiver checks these methods, actual sheet attachment, captured Force retry and original-icon availability with injected LFS responses against Apple Git and the bundled engine. See status-action QA. Physical menu/pointer/keyboard input is not established by these checks.

Commit now adds an optional LFS Lock owner column to its saved header layout. It is offered only with the common-directory LFS marker, and stays hidden by default. Showing it refreshes ownership; hidden columns do not request locks. The owner participates in case-insensitive sorting, path ties, autosizing and visible-column clipboard output. Lock state is independent of a nonempty owner name. Known uniformly locked selections offer Unlock, uniformly unlocked ones offer Lock, and mixed selections offer neither. A first query failure leaves ownership unknown instead of presenting files as unlocked; Cancel interrupts an in-flight owner query. A cancelled complete Working Tree reload retains its prior table and ownership atomically, and a late query cannot overwrite that snapshot. A subsequent successful empty reply publishes known-empty ownership. Existing visibility/order/width preferences migrate additively. See owner-column QA.

Working Tree now offers a saved LFS Lock visibility choice in its native header menu. Its default six columns stay visible. The seventh physical column is hidden by default and unavailable without an LFS marker. Showing it queries ownership; known locked/unlocked/mixed and unknown menu rules share Commit’s policy. Owner sorting uses the shared case-insensitive comparison and path tie; all seven headers retain native ascending/reverse bindings and one sort column. Closing during an owner query cancels it and does not publish a late response. LFS batches capture paths in the displayed sort order. See Working Tree owner QA.

Finder routing, remaining source availability gates and full locking progress fidelity remain incomplete. The native list adds an explicit Refresh button alongside F5. Physical keyboard/menu/pointer behavior, light/dark appearance, accessibility, fresh real screenshots, signed Finder deployment and provider acceptance remain pending. This is partial LFS parity and does not establish whole-application or App Store readiness.

The Locks dialog now uses a native three-state Select/deselect all checkbox: none, all and partial selection are visible as off, checked and mixed. Clicking an off checkbox selects all; clicking checked or mixed clears all, following upstream OnBnClickedSelectall. The target reads the current valid checked-ID count, preserving correctness between rapid activations before SwiftUI redraw. Busy, Quit-confirmation and empty-list states disable the control; highlighting remains independent. Add, Revert and Submodule Update supply live counts to the same shared native helper. Resolve now reuses it too, including the disabled busy state. Its native checkbox is checked against a private repository with two real merge conflicts; checkbox changes leave the index untouched. See three-state QA.

Working Tree’s owner column now participates in the shared native saved layout, adjusted widths, fitting, confirmed reset and visible-column clipboard output. Filename and File size are optional too; the six default visible columns and LFS availability gate remain. Existing owner visibility migrates additively. See Working Tree column QA. Physical/signed/provider acceptance remains pending for both lists.

Standalone Locks columns and clipboard

The native Locks table now shares saved column visibility, order, adjusted widths, automatic/content fitting and confirmed reset with Commit and Working Tree. Its available columns match LFSLocksDlg Init: Path, Filename, Extension, Last modified, File size and LFS Lock. Path, Extension and LFS owner are visible by default, alongside the independent checkbox column. Path stays visible; the checkbox stays first. Preferences use LFSLocks.FileColumns independently of the other dialogs. Reset No keeps the layout; Yes restores the source default.

All six text headers support ascending/reverse sorting with path ties. Owner uses case-insensitive text comparison; paths/names use numeric comparison and byte ties. Size/date come from local filesystem metadata once per lock refresh; remote files missing locally remain listed with unavailable metadata. Sorting retains server lock IDs, checked targets and highlighted rows independently. Busy, Quit confirmation and progress review block layout/sort changes.

Original-icon Copy to Clipboard offers full/relative paths, names and all visible information. Output uses displayed row and visible-column order with headings for multiple columns and native LF. The shared native interaction also routes keyboard copy, checkbox Space and clicked-column copy using server IDs, without manufacturing Git status records. Shift-copy includes source-style Unknown status because remote lock records contain no Git working-tree action.

See Locks column QA for native table/header, layout reopening, fitting/reset, sorting, copy text and operation checks. Physical gestures/keyboard/context menus, actual reset alert buttons, light/dark appearance, accessibility, fresh screenshots, authenticated providers and signed Finder/sandbox deployment remain unverified. Full Locks workflow parity remains partial.

Other shared-list context commands and source enablement remain pending; the column checks do not establish full menu parity.

A completed LFS batch now stops accepting queued per-file progress callbacks before publishing its final results. Previously a refresh yielding to another actor could append delayed callbacks to those results a second time. The native receiver preserves the exact per-file result count/order and cancellation checks; the failed diagnostic log records the duplicate rows before the fix.

Source context targets and copy masks

The standalone Locks context menu now uses the shared ownership policy: Lock and Unlock are both offered when the owner column is hidden; visible locked rows offer Unlock. The common-directory LFS marker, nonempty valid selection and non-directory gates match AppendLocksMenuItems. Context batches capture highlighted server IDs in displayed order, independently of checked targets. They start without Force, even when the dialog’s Force checkbox is checked. The main Unlock button captures checked paths and its Force setting instead. Explicit Force retry keeps the captured Unlock targets; failed Lock cannot be retried as Force Unlock. Owned progress titles and original artwork reflect the chosen operation. Closing standalone batch results refreshes the lock list.

The shared clipboard formatter now retains Copy all headings when only one column is visible, following the source’s multi-column command mask. Explicit single-column and full/relative/name copies still omit headings. Commit/Log Core formatting, Working Tree and Locks use the same heading rule.

Menu/copy QA records focused Core assertions and native operation/sheet/selection/Force checks with injected responses. Physical context-menu activation, full source command coverage, real providers and signed deployment remain pending.

Refresh choices and list position

Locks remembers checkbox choices by repository path across refreshes, including removed paths that later return with a different server lock ID. New paths are checked by default. Select all updates each current path's remembered choice. Context Lock/Unlock clears the remembered choices only for its captured targets; the checked Unlock button retains them. This follows the pinned status list's checked-path map and LFS context handlers.

With RememberFileListPosition enabled (the source default), refresh restores the scroll origin, first highlighted row index and focus mark index after the native table has adopted the new rows. Additional highlighted rows are not restored. The native implementation also restores row zero; the source's integer truth check skips that row. Disabling the preference resets scrolling and highlighting without changing checked targets. Pending restoration is invalidated by a newer refresh or table teardown.

Refresh QA records the checks and their limits.

Progress review and refresh order

The standalone Locks window now follows OnBnClickedUnLock and the status-list LFS context handlers: the server operation completes, the user reviews results (and may retry Force Unlock), then Close dismisses the owned sheet and refreshes the lock list. No query runs during review or between Force retries. Checked choices, highlighting and the existing lock rows remain intact until dismissal; context-target checkbox memory resets when the results close.

Close reserves the model's busy state before detaching the sheet, so a new batch, Refresh or duplicate Close cannot overlap the single follow-up query. That query uses a fresh cancellation token, including after a cancelled operation. Failed refresh clears the list and preserves exact per-file results and the operation summary. Commit and Working Tree continue to refresh their owner on closing results; their shared operation model does not query remote locks independently.

Review/refresh QA records query counts, actual sheet detachment, blocked overlapping commands, Force target retention, cancellation and failed-refresh result preservation. Physical input, full progress-dialog fidelity and authenticated provider acceptance remain pending.

Successful Lock opens Pull

After every target is locked successfully, TurtleGit opens the existing native Pull options dialog for the same repository and access lease. This follows LFSSetLockedProgressCommand's post-command callback and GitProgressDlg::OnCmdEnd: Pull opens when the batch ends, while Lock results are still available for review. Closing the results later retains the normal owner/list refresh.

The follow-up is wired from standalone Locks, Commit and Working Tree. Partial failure, thrown errors, cancellation and Unlock do not open Pull. Opening the options dialog does not execute Pull; the user chooses options and starts the existing Pull workflow.

Follow-up QA records actual native Pull controller construction/local options loading, controller callback routing, success/failure/cancellation gates and repository preservation. Server replies are injected, and native windows stay hidden. Visible activation, physical interaction, authenticated LFS/Pull transport and signed sandbox access remain unverified.

LFS result status labels now use native neutral text for successful Lock/Unlock and the exact source Conflict color for failures, following GitProgressList's SetColorCode and ReportError. See Appearance and status color QA. The combined per-file result layout remains an adaptation; full progress rows/context commands and visual acceptance are still pending.

Finder continuation (2026-10-12): cached LFS marker metadata now drives the source nested group, with Show locked files for folders and Lock/Unlock for files. Live literal versioned-target preflight precedes file operations. Standalone progress ownership is supported in addition to owned sheets. The grouped actual receiver covers duplicate gates, Quit and once-only Close cleanup with injected responses. See FINDER-LFS-MAIL-PARITY.md and qa/finder-lfs-mail-batch-2026-10-12.json; physical/signed/real-server acceptance remains incomplete.

List readiness and operation ownership (October 12, 2026)

Refresh now remains busy until the native table has adopted the replacement rows and finished the requested scroll/highlight restoration. The bridge reports completion once, including superseded requests, missing tables and teardown. This aligns native list readiness with the source LocksThread completion order and prevents pending restoration from overwriting a subsequent row selection. The original positional selection/checkbox semantics and source columns remain.

Forced closure retires standalone Locks queries and shared Lock/Unlock progress. It cancels their tokens, detaches their owned sheets, and rejects later provider results, streamed rows, errors and Pull follow-ups. Commit and Working Tree close and retire their LFS children, and completion callbacks check the current child identity and owner state before refreshing. Normal result review still refreshes once after dismissal; Force retry retains its captured targets. Cancellation reports completed server changes as retained. A model-wide active-operation count prevents application Quit before retired queries/operations settle.

The hosted failure at fd27870 occurred in the LFS selection-binding assertion before Send Mail began; the preceding grouped Merge/Patch/daemon phases passed. The assertion and its sorting checks are retained, with additional diagnostics. This implementation batch adds late query/result/Pull, owner-close and bridge teardown checks. The unsigned Debug build passed. Preceding grouped Merge/Patch/daemon phases passed, then LFS checks passed before a new fixture cleanup crash. Correcting that fixture's NSWindow release ownership allowed the affected LFS/mail retry to pass, including loopback SMTP and MIME assertions. Assertions and deadlines were retained; owned receiver/server processes were reaped. No Core suite was repeated for this native-only batch. See actual results and failures. Actual LFS servers, signed sandbox runtime and displayed light/dark acceptance remain unverified.

Captured menus, checkboxes and source progress — October 15, 2026

The checkbox handler now follows GitStatusListCtrl::OnLvnItemchanged: clicking a selected row propagates the new state across selected rows; an unselected row changes only itself. Space retains marked-row inversion. Row context actions and the dynamically inserted current-column Copy command capture the initiating IDs, paths, displayed order and columns. Selection/sort changes cannot retarget them; refresh, metadata/policy replacement, operation review, busy/quit and retirement refuse stale actions. Owning preferences apply to both SwiftUI menu icons and the native column-copy item.

LFSSetLockedProgressCommand/GitProgressList's Command, Lock/Unlock file and separate Error notifications now replace the former Path/Result/Message table. Literal file paths remain single file notifications; error messages split into source lines. A Core file-begin callback precedes command launch, so long operations show the active path immediately. An ordered mailbox drains live starts/results and the authoritative final batch supplies final rows. Native selected-row Copy and Command-C use path/message text, matching the source progress clipboard shape. Old progress menu objects cannot copy from a subsequent Force attempt.

The native table uses the original LockBackground/UnlockBackground artwork with the saved background preference. Command gray uses Colors.Cmd and shared native color conversion; file rows remain neutral, errors use Conflict and completion uses the common success/failure colors. The completed/total indicator, retained active path, source-scoped titles and Force review are shared by standalone, Add, Commit, Working Tree and Finder progress. Initiating dialogs pass their presentation preferences into their child. Per-attempt action logs save the recorded rows; retry records the previous attempt once, and closing review records the final attempt once.

The new LFS guide is the 47th bundled Help topic. The six controls in IDD_LFS_LOCKS have partial native mappings: list, select-all, Force, Unlock, Cancel and Help. This does not certify the dialog or complete common progress.

Native light/dark main-window captures are published without alteration: light, dark. The raw light progress sheet and dark progress sheet retain compositor padding and remain QA evidence, outside the public gallery. They show the actual injected mixed result, not authenticated server acceptance.

The ten focused Core cases, Debug build, both new native engine cases, both retained native regression cases and the affected Help check are recorded in exact evidence. Native repairs were fixture raw-string termination, per-engine private log isolation and two old unscoped- title assertions. The initial app build had one capture-list warning, repaired before the native check; Core was not repeated for that native-only change.

At that checkpoint remaining gaps included the lock-list watermark (now rendered by LFSLocksNativeTable using the original LockBackground.ico and ShowListBackgroundImage setting); complete progress file menus/double-click/sorting; exact completion wording and common timing-policy comparison; physical checkbox/menu/keyboard/VoiceOver and sheet/compositor sizing; authenticated LFS/Pull, signed grants/Finder and full dialog acceptance. No complete LFS/application parity is claimed.

Progress file actions and interaction — October 15, 2026

Pinned GitProgressList::WC_File_NotificationData supplies the next native progress interaction batch. A single file row offers Show log, Open, Open With, Explore to, LFS Lock and LFS Unlock, with original command artwork and source separators. Directories omit Open/Open With. Multiple or auxiliary rows offer Copy only. Actions capture their row and attempt, so sorting/selection cannot retarget them; Force retry, busy operation, Quit confirmation and retirement refuse obsolete invocations. Double-click opens a file or reveals a directory; auxiliary rows have no double-click action.

Header clicks sort only contiguous file blocks between auxiliary command/error/ completion messages. Action uses its text then the path; Path compares paths without numeric sorting. The native comparison is a macOS adaptation of FastCompareNoCase, not proven identical for every Unicode casing pair. Selection stays attached to notification identities. Sorting is refused while an operation or application chooser owns the progress window.

The earlier clipboard description above applies to the earlier implementation. The source has two distinct formats: the context menu copies path/message text and trims trailing whitespace only; Command-C copies Action: Path plus the source's two spaces and line ending for each selected row. The Mac uses LF. Command-A selects all notifications. Keyboard copying is available during a running operation, as in PreTranslateMessage; the context menu remains blocked. Completion now always uses Success/Fail (milliseconds ms @ local date/time), independently of ShowGitexeTimings, matching this progress class's policy.

Open With owns the native application picker and retains the application and repository grants through launch completion. Close/Force and Quit cannot bypass that ownership; forced owner retirement cancels its picker and refuses a late choice. The app's history routes retain the usual configured Log commands and independent history window lifetime. A fallback history controller is retained for standalone hosts without an app route. Child LFS progress and fallback history controllers close with their owning host; that differs from upstream's separate process windows. System application launch and Finder reveal still require physical/signed acceptance. The main lock-list watermark is now rendered through the shared native table; complete dialog geometry/accessibility acceptance remains open.

Both native engine cases passed in one grouped run, including the retained LFS interaction checks. No Core run was needed for native-only changes. See the progress-action evidence for exact builds, assertions, simulations and remaining acceptance work.

Native lock list — October 15, 2026

IDD_LFS_LOCKS now uses an AppKit table instead of the SwiftUI Table/interaction bridge. One coordinator owns checkbox events, row selection, sorting, header layout and menus. The original LockBackground artwork now appears in this main list as well as progress. Private background/icon/font/tooltip preferences apply to the owning dialog. The main-window background gap recorded above is closed. The new unmodified light/dark captures replace the gallery's earlier list captures.

Checking a selected row propagates to selected rows; Space uses the marked row. Keyboard Copy uses the captured displayed selection, and F5 runs the existing owned refresh. Source Lock/Unlock menus and all existing clipboard choices now use native menu items with original artwork. Current-column Copy captures the initiating rows, order and column; later refresh or policy changes expire it. There is no file-opening double-click on this list, as in LFSLocksDlg.

Headers expose the six source-supported text columns, fitting/default widths and Reset columns. The checkbox column stays fixed at the front and Path cannot be hidden. Saved order/width/visibility and first-descriptor sorting survive reopen. Refresh restores the viewport, first selected row index and separate focus mark when enabled; unchecking RememberFileListPosition clears them. Native layout is settled directly, removing the bridge's asynchronous configuration/restoration retry loop. Pending Reset questions retain operation/Quit ownership and their repository grant; forced close cancels the owned question and refuses late edits.

The initial build exposed an integer font-size type mismatch, corrected before execution. The new interaction group passed with both engines; the retained regression first stopped on a leftover bridge-only fixture reference. The native replacement also now explicitly retains the separate focus index. Exact grouped results are recorded in native-list evidence. Core is unchanged. Physical gestures/VoiceOver, large-list performance, exact source geometry, authenticated LFS and signed Finder/App Store acceptance remain open. This is not complete dialog or application certification.

Exact lock paths and connected owners — October 17, 2026

The pinned LFSLocksDlg::LocksThread / OnBnClickedUnLock and LFSSetLockedProgressCommand::Run retain checked file targets, emit a notification before each operation, continue after individual failures and offer Force unlock for the original selection. The native lock list, per-path progress and Force continuation now preserve distinct valid UTF-8 spellings throughout that sequence. The source list arrangement, original artwork, captured menu order and post-lock Pull remain unchanged.

Lock queries preserve exact path/owner text; path-keyed checkbox memory, Commit/Working Tree owner maps and owner-column clipboard use GitPathMap. LFS eligibility joins exact index/HEAD paths, including staged deletions, without admitting an unversioned canonical neighbor. Backend batch de-duplication keeps only repeated exact paths and retains both canonical spellings. Result identity and equality use exact bytes; result IDs encode the path for native collection consumers. The lock server's opaque IDs remain separate from file names and use exact checked/highlighted membership in the AppKit list.

Changing server IDs on refresh restores each path's own check state. The native list preserves its source first-selection-index/viewport policy; this is not a new path-based multi-selection refresh policy. Identical-looking lock paths expose UTF-8 bytes in tooltip/accessibility help. Lock-list headers and menus now use the existing native localization resources while keeping raw paths and owner names literal.

Each captured lock-list menu runs at most once for its original rows and columns. Selection and sort changes preserve that snapshot, as before; refresh, column policy, a busy owner or retirement refuse it. Progress ignores duplicate and out-of-scope callbacks and validates final result membership before replacing reviewed rows or offering successful Lock → Pull. Force retry captures the same exact original paths even when current selection/checks change. Cancellation and closed owners keep their existing generation and operation-lifetime fences.

Physical filesystem aliasing is unchanged: two Git index paths can name the same file on macOS. This work preserves distinct index/server identities and does not create independent physical files. Invalid UTF-8 names, authenticated remote LFS, physical popup/keyboard/VoiceOver and signed installed Finder acceptance remain open. Complete LFS/source dialog and application certification is not claimed.

The grouped checkpoint passed 24 focused Core checks, one Debug app build and four native case/engine combinations on the first invocation, with no repairs or repeated checks. The native family uses system and bundled Git, private repositories, preferences and simulated LFS replies; no remote authenticated locking is claimed. All four receivers were reaped and independently absent. Existing build warnings and the zero-exit driver diagnostic are retained in batch evidence. No new visual capture certifies the full dialog.

Direct LFS commands and retained ownership, 2026-10-18

The primary command router now accepts lfslocks, lfslock, and lfsunlock. Only Unlock accepts /force or --force. Native repeated paths preserve literal asterisks, Unicode and newlines; legacy /path: keeps its source * separator. UTF-8/UTF-16/NUL path files use the existing authorized, bounded reader and optional explicit deletion. Force survives resolution and repository discovery.

As in the pinned LFSCommands.cpp, Locks opens the server-wide list, while Lock/Unlock execute the selected paths through native progress. A later Locks request focuses its current window and preserves checks, Force and result review. Both list and standalone progress inherit the workspace's presentation settings. Direct actions validate the complete literal batch before contacting Git LFS, including missing/unversioned files for which Git LFS supplies the actual result. Finder retains its stricter versioned-file eligibility check. Direct commands refuse directories, administration paths, escapes and bare repositories.

Selection preparation retains the original repository/access/window. Closing the launching window or retiring the workspace cancels that read; even an uncooperative late reply cannot open progress. Pending work remains accounted for until it actually drains. Progress supports a parent sheet or standalone window, per-file results, cancellation, explicit failed-Unlock Force retry and existing Log/Pull post-actions. Closing a result refreshes matching Commit/Working Tree views.

The hosted failure at generated LFSReceiver.swift:688 occurred before SMTP readiness. Its assertion expected ownership to be empty after cancellation of a previously loaded Working Tree table. A single local reproduction observed the same two owners/locked paths before and after cancellation, including Zebra, with no late Late owner. The corrected assertion checks the complete retained snapshot, then requires the next successful empty query to publish known-empty ownership. This preserves behavioral assertions rather than clearing valid data to satisfy the old expectation. Validation results are recorded separately in batch evidence. Public-provider authentication, physical input/visual parity, full hosted CI and signed App Store acceptance remain outside this local check.

Connected LFS completion and native readiness — October 18, 2026

The original LFS progress command reports each completed file, continues through ordinary file errors and retains the captured selection for an explicit Force unlock. Native progress now also handles a backend that terminates without a complete final list: valid live results remain in original selected-path order, and matching final records supersede those notifications. An incomplete, noncancelled final reply is an error, cannot open Pull, and cannot display a successful completion. Failed Unlock, including an incomplete reply with no failed per-file row, offers Force against the complete original selection. Cancellation retains reported server effects without asserting that unfinished files succeeded; it never opens the successful Lock → Pull follow-up.

File-lock preparation captures its preference store and progress factory before asynchronous eligibility work. A later workspace setting/context change cannot retarget the child. Locks window ownership uses exact UTF-8 repository keys and identity-checked close callbacks, consistent with the other conflict/file owners. Standalone Locks refresh still clears its list while reading, matching the source CLFSLocksDlg::LocksThread; Commit/Working Tree complete-snapshot reloads retain their separate atomic cancellation policy.

The hosted run at source 88efaf6c passed the corrected cancellation-snapshot assertions, then stopped at generated LFSReceiver.swift:702, waiting for the Working Tree owner column to hide. That generated location is source fixture line 701. The fixture had dispatched the header action after model completion without waiting for delivery of the enabled native target. Delayed delivery is the current explanation to verify on the hosted SDK. It now waits for the actual header's enabled/on state and owning probe, then retains the existing hidden-column and both-actions assertions. It does not extend the timeout, remove an assertion, or force the production state to hide the column.

Batch evidence records actual validation and attempts. Private injected replies cover completion/cancellation; authenticated providers, physical header input, arbitrary invalid UTF-8 names, full hosted CI, whole-dialog appearance/accessibility and current signed Finder/App Store acceptance remain open.

Clone checkout-filter continuation — October 19, 2026

The Clone checkout family connects configured custom smudge filters to selected libgit2 Clone and its recursive checkout option. It distinguishes initial destination cleanup from later recursive partial work, retains bare/no-checkout suppression and owns actual filter cancellation/progress. Configured LFS one-shot smudge, source boundaries and grouped evidence are tracked in that family; it does not claim persistent filter-process or complete providers.