Skip to content

Rewrite GUI with tabbed UI, fix broken build, de-panic mount setup - #3

Merged
ArturLauche merged 8 commits into
mainfrom
claude/sweet-lovelace-rnwbk2
Jun 13, 2026
Merged

Rewrite GUI with tabbed UI, fix broken build, de-panic mount setup#3
ArturLauche merged 8 commits into
mainfrom
claude/sweet-lovelace-rnwbk2

Conversation

@ArturLauche

Copy link
Copy Markdown
Owner

Summary

The GUI binary did not compile at HEAD — an E0382 borrow-after-move in start_mount (mount_point moved into self.active_mount_point, then borrowed on the next line) shipped unnoticed because ci.yml lints every feature combination except gui. This PR fixes the build, rewrites the GUI for a better UX and stability, hardens the library's mount-setup path, and closes the CI gap.

GUI rewrite (src/bin/hf-mount-gui/, replaces the 2,637-line single file)

Layout / UX

  • Real tabbed layout — Mount (form + actions), Activity (session log with copy), Setup (full checks with per-check fix actions) — replacing the previous decorative sidebar whose nav items didn't navigate.
  • Bottom status bar: state chip, headline/detail, mounted elapsed time, platform label.
  • The mount form lives in a scroll area, so short windows no longer clip the advanced options and buttons.

Stability

  • Background-worker status is read by a dedicated poller thread (2 s interval). Previously every UI frame spawned tasklist.exe and stat-ed a possibly-wedged NFS drive on the UI thread — up to dozens of subprocess launches per second during interaction, and multi-second freezes on a hung mount.
  • Unmount commands run on a worker thread instead of blocking the UI.
  • Foreground mounts stop through a cooperative MountShutdown handle: Stop now works while the mount command is still retrying, not only after a successful mount. Window close uses the same path with a bounded grace period plus a forced unmount fallback.

New features

  • Windows free drive-letter picker (single GetLogicalDrives syscall — no per-letter probing that could hang).
  • Token show/hide toggle; inline source-ID validation; recent-sources dropdown for one-click refill; copy session log; copy worker-log path; per-check fix actions (Enable NFS / Restart as admin / copy command) in Setup.

Library hardening

  • setup::build / build_with_runtime now return Result instead of panicking on every config/auth error (new Error::Setup variant). The FUSE sidecar drops its catch_unwind-and-parse-the-panic workaround; CLI binaries print a clean error and exit.
  • nfs::mount_nfs_with_callback takes an NfsMountParams struct with an optional MountShutdown; Linux/macOS mount commands now use tokio::process (no blocking the runtime); the mount-disappeared probe runs via spawn_blocking; the Windows Error-53 retry loop no longer ends in unreachable!() and is cancellation-aware.
  • New hf_mount::windows module deduplicates the drive-letter/System32 helpers previously copy-pasted in nfs.rs, setup.rs, and the GUI; the pure parsing logic is now unit-tested on Linux CI.
  • StagingDir::new returns Result instead of panicking.

CI

  • ci.yml now runs cargo clippy --no-default-features --features nfs,gui --bins --tests -- -D warnings and the GUI unit tests on the Linux runner — this exact class of breakage is now caught on every PR without waiting for the Windows/macOS builders.

Verification

  • cargo clippy clean with -D warnings across all five feature combos (none, nfs, fuse, fuse+nfs, nfs+gui).
  • cargo test --lib --features fuse,nfs: 356 passed. --features nfs (Windows CI config): 356 passed. GUI bin tests: 8 passed.
  • cargo +nightly-2026-04-22 fmt --check clean (also fixes pre-existing drift in daemon.rs).
  • Full GUI binary build + CLI smoke (--version, --help, --check-setup exit codes) verified on Linux.
  • Windows/macOS GUI builds are exercised by this repo's windows-build.yml / macos-gui-build.yml on this PR.

https://claude.ai/code/session_01D3AdfdaNzP6eBm3seWGuJP


Generated by Claude Code

The GUI binary did not compile at HEAD (E0382 borrow-after-move in
start_mount) because CI never built the gui feature. This change fixes
the build, restructures the GUI, and hardens the library setup path.

GUI (src/bin/hf-mount-gui/, replaces the 2,637-line single file):
- Real tabbed layout (Mount / Activity / Setup) instead of a decorative
  sidebar; bottom status bar with state chip, detail, and mounted
  elapsed time; scrollable form so short windows no longer clip.
- Stability: background-worker status is now read by a dedicated poller
  thread (2s interval) instead of spawning tasklist.exe and statting a
  possibly-wedged NFS drive on every UI frame; unmount runs on a worker
  thread; foreground mounts stop through a cooperative shutdown handle
  that also works while the mount command is still retrying.
- New features: free drive-letter picker on Windows (GetLogicalDrives,
  no probing), token show/hide, recent-sources dropdown, inline source
  validation, copy session log, per-check fix actions in Setup.

Library:
- setup::build/build_with_runtime return Result instead of panicking;
  new Error::Setup variant; the FUSE sidecar no longer needs
  catch_unwind to report setup failures.
- nfs::mount_nfs_with_callback takes NfsMountParams with an optional
  MountShutdown for cooperative stop; Linux/macOS mount commands use
  tokio::process; the mount-disappeared probe runs via spawn_blocking;
  the Windows retry loop no longer ends in unreachable!().
- New hf_mount::windows module shares drive-letter/System32 helpers
  that were duplicated across nfs.rs, setup.rs, and the GUI; the pure
  parsing logic now has tests that run on Linux CI.

CI: clippy + unit tests for the nfs,gui feature combo on the Linux
runner, so GUI breakage is caught on every PR.

https://claude.ai/code/session_01D3AdfdaNzP6eBm3seWGuJP
@coderabbitai

coderabbitai Bot commented Jun 12, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 47074868-4e19-4f42-8bf8-d888391e50c2

📥 Commits

Reviewing files that changed from the base of the PR and between 4c7873d and ab35cab.

📒 Files selected for processing (5)
  • src/bin/hf-mount-fuse-sidecar.rs
  • src/bin/hf-mount-gui/app.rs
  • src/bin/hf-mount-gui/platform.rs
  • src/bin/hf-mount-gui/worker.rs
  • src/nfs.rs

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Native GUI: Mount, Activity, and Setup tabs; themed UI; Mount/Stop/Open controls; activity log with copy; recent-source dropdown and free drive-letter picker on Windows.
    • Background detached worker to keep mounts active and autostart-at-login across platforms.
    • Preflight checks with copyable setup commands and actionable Windows fixes; faster/responsive mount stop handling.
  • Documentation

    • Expanded Windows/macOS GUI setup and validation steps.

Walkthrough

Modularizes the GUI into many files, adds background-worker status-file IPC and worker polling, centralizes platform integration and preflight/autostart, implements theme/widgets/tabs, and converts setup/mount/staging flows from panic-based code to Result-returning constructors with cooperative NFS shutdown.

Changes

GUI Refactor & Setup Improvements

Layer / File(s) Summary
Entry point, Cargo, CI, README
Cargo.toml, src/bin/hf-mount-gui/main.rs, .github/workflows/ci.yml, README.md
New GUI binary entry file and CLI flags; CI adjusted to run lint/tests on ubuntu-hosted runners and gate expensive jobs to upstream-only; README expanded with Mount/Activity/Setup docs.
GUI core app state & lifecycle
src/bin/hf-mount-gui/app.rs
MountGuiApp state model, SharedStatus, mount start/stop orchestration (foreground cooperative MountShutdown and detached background worker), per-frame housekeeping, and eframe lifecycle handling.
Tabs, widgets and theme
src/bin/hf-mount-gui/mount_tab.rs, activity_tab.rs, setup_tab.rs, widgets.rs, theme.rs
Mount/Activity/Setup tab implementations, reusable egui primitives (buttons/chips/fields/segmented control), and apply_theme dark UI theme.
Profile persistence & validation
src/bin/hf-mount-gui/profile.rs
MountProfile/RecentSource JSON persistence, source-id validation, conversion to runtime Source/MountOptions, and tests enforcing token and recent-source behaviors.
Background worker, status file & poller
src/bin/hf-mount-gui/worker.rs, util.rs, autostart.rs
Detached background worker process, atomic status/log file IPC, worker run loop with panic-to-status handling, WorkerPoller for UI-friendly polling, shared utilities, and autostart install/detect/remove.
Platform integration & preflight
src/bin/hf-mount-gui/platform.rs, preflight.rs, src/windows.rs
Platform helpers for unmount/open/process liveness/termination/detach, Windows elevation and NFS helpers, free drive-letter enumeration, and OS-specific preflight checks with blocker commands.
NFS shutdown & unmount behavior
src/nfs.rs
Introduces MountShutdown and NfsMountParams for cooperative cancellation, makes mount commands interruptible, adds guarded liveness probes, spawn_unmount offload, and reworks unmount_nfs to best-effort boolean return.
Setup: Result-based build & runtime ownership
src/setup.rs, src/error.rs, src/xet.rs
Converts build_runtime/build/build_with_runtime to return Results, introduces Error::Setup and OwnedRuntime, makes Xet/StagingDir initialization fallible, and replaces panic/unwrap paths with propagated setup errors; sidecar now handles build failures explicitly.
Daemon & tests tweaks
src/daemon.rs, src/test_mocks.rs
Minor formatting-only error message changes and tests updated to expect staging-dir creation failures explicitly.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • ArturLauche/hf-mount#1: Related Windows NFS and mount behavior changes overlapping with this PR's nfs.rs updates.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main changes: GUI rewrite with tabbed UI, a build fix for the broken compile, and removal of panics from mount setup.
Description check ✅ Passed The description is comprehensive and directly related to the changeset, covering the GUI rewrite, library hardening, CI improvements, and verification details.
Docstring Coverage ✅ Passed Docstring coverage is 83.26% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/sweet-lovelace-rnwbk2

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Lint & Unit Tests failed in one second on this fork: the job targets the
huggingface-internal runner group (hf-mount-ci-pub), which forks cannot
use, so the main CI never actually ran here — which is also how a
non-compiling GUI landed on the default branch unnoticed.

Run lint-test on ubuntu-latest (works upstream too) and gate the
internal-registry setup plus the five integration jobs (smoke, fsx,
xfstests, pjdfstest, bench) to github.repository ==
'huggingface/hf-mount' so they skip cleanly on forks instead of queuing
forever on unavailable runners.

https://claude.ai/code/session_01D3AdfdaNzP6eBm3seWGuJP

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1de4f13515

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/bin/hf-mount-gui/app.rs
Comment thread src/nfs.rs Outdated
Comment thread src/bin/hf-mount-gui/app.rs
Comment thread src/bin/hf-mount-gui/worker.rs Outdated
Comment thread src/nfs.rs Outdated
- Stop now terminates a background worker that has not mounted yet
  (taskkill on Windows, SIGTERM on Unix) instead of running a doomed
  unmount while the worker carries on and mounts anyway; the status
  file is overwritten so later launches don't see a stale Mounting
  claim, and a belt unmount cleans a mount that raced the kill.
- A stale terminal worker status file no longer re-clobbers newer local
  status every poll: terminal reports are mirrored only when their
  content changes or at startup.
- Cancellation is reported as Stopped, not Failed: the Windows retry
  loop returns a clean-stop marker instead of an Interrupted error, and
  the GUI maps post-stop errors to Stopped.
- macOS/Linux mount commands race against the shutdown handle with
  kill_on_drop, so Stop interrupts a hung mount.nfs instead of waiting
  it out.
- WorkerPoller shutdown joins with a 250ms bound and detaches if the
  thread is blocked probing a wedged mount, so window close cannot hang.

https://claude.ai/code/session_01D3AdfdaNzP6eBm3seWGuJP

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7ac08ee02f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .github/workflows/ci.yml Outdated
Comment thread src/bin/hf-mount-gui/platform.rs
Comment thread src/bin/hf-mount-gui/worker.rs Outdated
Comment thread src/nfs.rs Outdated
Comment thread src/nfs.rs
Comment thread src/bin/hf-mount-gui/app.rs
- CI: gate internal-runner jobs and the registry setup on the PR *head*
  repository, not github.repository (which is the base repo on fork PRs
  and would have run untrusted fork code on internal runners).
- Unix worker termination signals the process group, so a mount.nfs
  helper spawned before the worker installs its SIGTERM handler dies
  with it instead of completing the mount post-kill.
- A failed worker spawn clears the provisional Mounting status file so
  the poller doesn't report a phantom live worker for the staleness
  window.
- unmount_nfs reports success; shutdown events now say when the unmount
  failed and the target needs manual cleanup instead of claiming a
  clean stop.
- The mount-liveness probe is its own select arm, so a probe wedged on
  a dead mount no longer blocks the shutdown/signal/UMNT branches.

https://claude.ai/code/session_01D3AdfdaNzP6eBm3seWGuJP

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: baf9aa1869

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/bin/hf-mount-gui/platform.rs Outdated
Comment thread src/bin/hf-mount-gui/worker.rs Outdated
Comment thread src/nfs.rs
…ntime teardown

- mount_point_appears_active now consults the platform mount table /
  filesystem type (shared nfs::is_mounted, newly public) instead of
  Path::exists, so a leftover directory from a crashed worker or a
  reboot no longer reads as a live mount that pins the GUI.
- Worker PIDs read back from the status file are verified to still
  identify as an hf-mount worker (cmdline marker on Linux/macOS, image
  name on Windows) before being trusted for liveness or termination —
  a recycled PID can no longer get an unrelated process killed. Stale
  records are cleared instead.
- The owned tokio runtime tears down via shutdown_timeout(5s) through
  an OwnedRuntime guard, so a blocking probe wedged on a dead mount
  cannot stall Stop or window close at runtime-drop time.

https://claude.ai/code/session_01D3AdfdaNzP6eBm3seWGuJP
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 10

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/ci.yml:
- Around line 23-29: Add persist-credentials: false to the actions/checkout step
so the workflow token is not written into local git config for the fork-exposed
job; locate the checkout step using the
actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd reference and add the
persist-credentials: false property under that step to explicitly disable Git
credential persistence.

In `@src/bin/hf-mount-gui/app.rs`:
- Around line 829-833: The early return in on_exit() when self.active_background
is true can abort a running background stop started by stop_mount(); modify
on_exit() to detect an in-flight stop by inspecting self.stop_thread (or the
equivalent join/handle stored by stop_mount()) and wait for it to finish (or
join it) before returning, using a bounded timeout/grace period to avoid
blocking forever; ensure you clear or take the handle (e.g. take() the Option)
so the join only happens once and preserve the existing active_background logic
so foreground behavior is unchanged.

In `@src/bin/hf-mount-gui/platform.rs`:
- Around line 204-205: The current Windows check uses
stdout.contains(&format!(",\"{pid}\",")) which can match the PID string in other
columns; update process_is_running to parse the CSV output explicitly: read
stdout line-by-line as CSV (e.g., csv::ReaderBuilder::from_reader or a simple
CSV split that respects quotes), extract the PID column (column index 1 in
tasklist CSV rows) and compare that field exactly to pid.to_string() instead of
using stdout.contains; replace the stdout.contains call and refer to the pid
variable and process_is_running function when making the change.

In `@src/bin/hf-mount-gui/profile.rs`:
- Around line 108-110: The validator currently only checks trimmed.contains('/')
which still allows values like "a/b/c"; update the inline check for source ==
GuiSource::Bucket to split trimmed by '/' and ensure there are exactly two
non-empty segments (e.g. parts.len() == 2 && !parts[0].is_empty() &&
!parts[1].is_empty()); if the check fails return the same user-facing message
("Buckets are namespace/bucket, e.g. myuser/my-bucket.") so invalid bucket IDs
with zero, more than one, or empty segments are rejected early.

In `@src/bin/hf-mount-gui/util.rs`:
- Around line 95-103: The Windows branch in write_file_replace currently calls
std::fs::remove_file(path) before std::fs::rename, which can permanently lose
the original on a rename failure; remove the pre-delete and let std::fs::rename
perform the replace (or, if you need stricter Windows semantics, replace the
rename path with a Windows single-step replace primitive such as ReplaceFileW),
i.e., eliminate the remove_file(path) call and ensure error handling still
cleans up temp_path on failure while reporting the original and temp paths in
the error message.

In `@src/bin/hf-mount-gui/worker.rs`:
- Around line 235-247: Wrap the early startup sequence (calls to
load_mount_profile, profile_mount_source, profile_mount_options) so any Err
triggers a worker-owned status update that overwrites the provisional Mounting
record: catch the error, call write_worker_status with WorkerState::Failed (or
appropriate error state), a short message like "Background worker failed to
start", the error string (format!("{}", err)) as details, include
Some(std::process::id()) as the owner and the best-known mount point (or None if
unavailable), then return the original error; use the existing functions
append_worker_log and write_worker_status and the existing symbols
load_mount_profile, profile_mount_source, profile_mount_options to locate where
to add the error-handling/status-write logic.
- Around line 66-84: The read_worker_status() loop currently retries parse
failures but returns immediately on std::fs::read() errors; change it to treat
transient read errors (at least std::io::ErrorKind::NotFound and
PermissionDenied which happen during write_file_replace() on Windows) as
retryable: if std::fs::read(&path) returns an Err and attempt < 2, sleep briefly
and continue the loop, otherwise return the formatted error as before; keep
references to worker_status_path(), path, and read_worker_status() to locate the
change.

In `@src/nfs.rs`:
- Around line 926-941: The select branches call unmount_for_shutdown(...)
directly (and its fallback runs a blocking Command::status()), which can wedge
the task and prevent subsequent cleanup (server_handle.abort(),
portmapper_handle.abort(), vfs_for_shutdown.shutdown()); move the unmount work
off the select path by spawning it into a blocking task
(tokio::task::spawn_blocking or spawn) and await it with a timeout
(tokio::time::timeout) so the select branch can immediately proceed to break and
perform abort/shutdown even if unmount hangs; update the branches that call
unmount_for_shutdown and the fallback Command::status path to kick off the
offloaded unmount task and handle its result asynchronously (log
success/failure/timeout) without blocking the main shutdown flow.

In `@src/setup.rs`:
- Around line 339-343: build() currently calls build_runtime() which can panic
(via expect) and therefore bypass the Result error path; change build_runtime()
to return Result<tokio::runtime::Runtime, SetupError> (or appropriate error
type) instead of panicking, update its callers (including build_with_runtime if
needed) to accept a Runtime by value, and in build() call the fallible
build_runtime(), propagate any error as Err(...) instead of letting it abort,
then proceed to call build_with_runtime(source, options, is_nfs,
runtime.handle().clone()), set setup._owned_runtime = Some(runtime) and return
Ok(setup); ensure the unique symbols mentioned (build(), build_runtime(),
build_with_runtime(), MountSetup, _owned_runtime) are updated to match the new
fallible contract.

In `@src/xet.rs`:
- Around line 209-214: The code in StagingRoot::new currently uses
std::fs::create_dir_all which silently succeeds if a staging-* path already
exists, allowing collisions; change to attempt exclusive creation (use
std::fs::create_dir) and retry with a new random name on EEXIST until success
(or give up after a bounded number of attempts and return an Error).
Specifically modify the pub fn new(cache_dir: &Path, max_bytes: u64) ->
crate::error::Result<Self> to loop generating
cache_dir.join(format!("staging-{:016x}", rand_u64())) and call
std::fs::create_dir(&dir) (not create_dir_all), treating
std::io::ErrorKind::AlreadyExists as a retry case and other errors as failures;
ensure the final processLogger/Error message includes the dir and underlying
error and keep StagingRoot::drop semantics intact.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 0173569c-be5f-431b-896d-46f5f6988aa0

📥 Commits

Reviewing files that changed from the base of the PR and between f18db94 and baf9aa1.

📒 Files selected for processing (26)
  • .github/workflows/ci.yml
  • Cargo.toml
  • README.md
  • src/bin/hf-mount-fuse-sidecar.rs
  • src/bin/hf-mount-gui.rs
  • src/bin/hf-mount-gui/activity_tab.rs
  • src/bin/hf-mount-gui/app.rs
  • src/bin/hf-mount-gui/autostart.rs
  • src/bin/hf-mount-gui/main.rs
  • src/bin/hf-mount-gui/mount_tab.rs
  • src/bin/hf-mount-gui/platform.rs
  • src/bin/hf-mount-gui/preflight.rs
  • src/bin/hf-mount-gui/profile.rs
  • src/bin/hf-mount-gui/setup_tab.rs
  • src/bin/hf-mount-gui/theme.rs
  • src/bin/hf-mount-gui/util.rs
  • src/bin/hf-mount-gui/widgets.rs
  • src/bin/hf-mount-gui/worker.rs
  • src/daemon.rs
  • src/error.rs
  • src/lib.rs
  • src/nfs.rs
  • src/setup.rs
  • src/test_mocks.rs
  • src/windows.rs
  • src/xet.rs
💤 Files with no reviewable changes (1)
  • src/bin/hf-mount-gui.rs

Comment thread .github/workflows/ci.yml
Comment thread src/bin/hf-mount-gui/app.rs Outdated
Comment thread src/bin/hf-mount-gui/platform.rs Outdated
Comment thread src/bin/hf-mount-gui/profile.rs Outdated
Comment thread src/bin/hf-mount-gui/util.rs Outdated
Comment thread src/bin/hf-mount-gui/worker.rs
Comment thread src/bin/hf-mount-gui/worker.rs
Comment thread src/nfs.rs Outdated
Comment thread src/setup.rs
Comment thread src/xet.rs Outdated
…utdown

- write_file_replace no longer pre-deletes the destination on Windows;
  std::fs::rename replaces atomically (MoveFileExW), closing a crash
  window that could lose the old file.
- read_worker_status retries transient NotFound/PermissionDenied reads
  that can surface mid-replace on Windows, not just parse errors.
- Background worker writes a Failed status if profile/source/options
  loading fails, overwriting the GUI's provisional Mounting claim instead
  of leaving it live for the staleness window.
- Windows worker liveness parses the tasklist PID column explicitly
  rather than substring-matching the row.
- Bucket IDs must be exactly namespace/bucket (reject extra/empty
  segments) at validation time, not deferred to mount setup.
- on_exit waits (bounded) for an in-flight background stop thread so
  closing the window can't abort an unmount and orphan the mount.
- Shutdown-time unmounts run on the blocking pool and are awaited with a
  10s timeout, so a wedged umount can't delay server/portmapper/VFS
  teardown.
- build_runtime returns Result; build() surfaces runtime-creation
  failure as Error::Setup instead of panicking.
- StagingDir::new creates its dir exclusively and retries on collision,
  so a random-name clash can't share one staging root between mounts.
- CI: persist-credentials: false on the fork-exposed checkout.

https://claude.ai/code/session_01D3AdfdaNzP6eBm3seWGuJP

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 92a432f7f4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/bin/hf-mount-gui/app.rs
Comment thread src/bin/hf-mount-gui/platform.rs Outdated
Comment thread src/bin/hf-mount-gui/worker.rs
Comment thread src/bin/hf-mount-gui/app.rs Outdated
Comment thread src/bin/hf-mount-gui/app.rs
Comment thread src/bin/hf-mount-gui/profile.rs Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/nfs.rs (1)

1247-1252: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Linux is_mounted can report false negatives and trigger premature shutdown.

At Line 1251, comparing path directly to /proc/mounts field 2 is brittle (\040 escaping, normalization differences like trailing slash). That can make an active mount look “disappeared,” causing the shutdown path to fire incorrectly.

🔧 Suggested fix
 #[cfg(target_os = "linux")]
 {
+    let wanted = std::path::Path::new(path)
+        .canonicalize()
+        .unwrap_or_else(|_| std::path::PathBuf::from(path));
     std::fs::read_to_string("/proc/mounts")
-        .map(|s| s.lines().any(|line| line.split_whitespace().nth(1) == Some(path)))
+        .map(|s| {
+            s.lines().any(|line| {
+                line.split_whitespace()
+                    .nth(1)
+                    .map(proc_mounts_unescape)
+                    .map(std::path::PathBuf::from)
+                    .and_then(|p| p.canonicalize().ok().or(Some(p)))
+                    .is_some_and(|p| p == wanted)
+            })
+        })
         .unwrap_or(false)
 }
+
+#[cfg(target_os = "linux")]
+fn proc_mounts_unescape(raw: &str) -> String {
+    raw.replace("\\040", " ")
+        .replace("\\011", "\t")
+        .replace("\\012", "\n")
+        .replace("\\134", "\\")
+}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/nfs.rs` around lines 1247 - 1252, The is_mounted function currently
compares the raw mountpoint token from /proc/mounts to the input path, which
yields false negatives due to octal-escaped spaces (e.g. \040) and normalization
differences; fix is_mounted by normalizing both sides before comparison: parse
the mount lines as now, unescape octal sequences in the mountpoint token,
normalize/remove trailing slashes and then compare using Path semantics
(preferably try std::fs::canonicalize on both the provided path and the
unescaped mountpoint and fall back to a normalized string comparison if
canonicalize fails). Ensure you update the is_mounted implementation to perform
unescaping, path normalization, and canonicalization fallback so mounts with
escaped spaces or differing trailing slashes are detected correctly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/bin/hf-mount-gui/app.rs`:
- Around line 851-862: The code currently calls handle.join() unconditionally
which can block indefinitely; instead, after the bounded wait loop in the branch
that checks self.active_background and takes self.stop_thread, only call
handle.join() if handle.is_finished() (or the deadline was reached and the
thread has finished); otherwise drop the JoinHandle to detach the thread so
window close remains bounded. Update the block around self.stop_thread.take(),
the while loop that checks handle.is_finished(), and the join call so join is
conditional (e.g., if handle.is_finished() { let _ = handle.join(); } ) and do
not block if platform::unmount_path is wedged.

In `@src/bin/hf-mount-gui/platform.rs`:
- Around line 203-215: In worker_process_alive (function worker_process_alive in
src/bin/hf-mount-gui/platform.rs) the marker is checked with contains(marker)
which can match substrings inside other arguments; change the check to match the
marker as a full command-line argument: after getting the ps output, convert
stdout to a String, split it into arguments (e.g., whitespace-split or use a
shell-words parser if you need quoted args), and return true only if any token
== marker; keep the rest of the existing early-return/error handling intact.

---

Outside diff comments:
In `@src/nfs.rs`:
- Around line 1247-1252: The is_mounted function currently compares the raw
mountpoint token from /proc/mounts to the input path, which yields false
negatives due to octal-escaped spaces (e.g. \040) and normalization differences;
fix is_mounted by normalizing both sides before comparison: parse the mount
lines as now, unescape octal sequences in the mountpoint token, normalize/remove
trailing slashes and then compare using Path semantics (preferably try
std::fs::canonicalize on both the provided path and the unescaped mountpoint and
fall back to a normalized string comparison if canonicalize fails). Ensure you
update the is_mounted implementation to perform unescaping, path normalization,
and canonicalization fallback so mounts with escaped spaces or differing
trailing slashes are detected correctly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 254c0424-ed08-462d-b573-cf67de4dd372

📥 Commits

Reviewing files that changed from the base of the PR and between baf9aa1 and 92a432f.

📒 Files selected for processing (10)
  • .github/workflows/ci.yml
  • src/bin/hf-mount-fuse-sidecar.rs
  • src/bin/hf-mount-gui/app.rs
  • src/bin/hf-mount-gui/platform.rs
  • src/bin/hf-mount-gui/profile.rs
  • src/bin/hf-mount-gui/util.rs
  • src/bin/hf-mount-gui/worker.rs
  • src/nfs.rs
  • src/setup.rs
  • src/xet.rs

Comment thread src/bin/hf-mount-gui/app.rs Outdated
Comment thread src/bin/hf-mount-gui/platform.rs
…hutdown

- profile: restore bucket subfolder support (regression). Validation now
  requires >=2 non-empty segments instead of exactly 2, so
  namespace/bucket/path mounts that Source::Bucket supports are accepted
  again; still rejects empty interior segments.
- platform (Windows): validate the --background-worker marker via the
  process command line (PowerShell CIM), so a foreground GUI window that
  inherited a recycled PID is no longer mistaken for — or killed as — a
  background worker. Fails closed; Mounted liveness comes from the mount
  table so this only gates the brief Mounting/Stopping window.
- platform (macOS): match the worker marker as a whole ps argument, not a
  substring.
- worker: a recorded-but-dead/mismatched PID is now treated as stale
  immediately; the heartbeat-freshness fallback applies only to the
  provisional pid-less launch status. Mounted is confirmed via the mount
  table.
- app: reconcile an existing background worker synchronously at startup so
  a second GUI gates Start immediately instead of racing the poller and
  spawning a duplicate worker; on_exit waits (bounded) for any in-flight
  stop/cleanup thread and only joins if finished; post-termination cleanup
  unmount is tracked in stop_thread rather than detached.
- nfs: Linux is_mounted unescapes /proc/mounts octal escapes and
  normalizes trailing slashes so an active mount isn't misread as
  disappeared (string-only; no canonicalize that could block).

https://claude.ai/code/session_01D3AdfdaNzP6eBm3seWGuJP

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4c7873d165

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/bin/hf-mount-gui/worker.rs
Comment thread src/bin/hf-mount-gui/app.rs Outdated
Comment thread src/bin/hf-mount-gui/app.rs Outdated
Comment thread src/bin/hf-mount-gui/app.rs Outdated
Comment thread src/bin/hf-mount-fuse-sidecar.rs

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
src/bin/hf-mount-gui/platform.rs (1)

138-145: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Return real launcher failures from open_mount_point.

This path uses spawn(), so any successfully started xdg-open / open / explorer.exe process is reported as success even when it immediately exits non-zero for a missing or invalid target. src/bin/hf-mount-gui/app.rs logs "Opened mount point" on Ok(()), so the GUI currently reports success for failed open attempts.

Suggested fix
 pub fn open_mount_point(mount_point: Option<&Path>) -> Result<(), String> {
     let mount_point = mount_point.ok_or_else(|| "No active mount point is recorded.".to_string())?;
     let target = open_target(mount_point)?;
+    if !Path::new(&target).exists() {
+        return Err(format!("Mount point does not exist: {target}"));
+    }
 
-    open_command(&target)
-        .spawn()
-        .map_err(|e| format!("Failed to open mount point: {e}"))?;
+    let status = open_command(&target)
+        .status()
+        .map_err(|e| format!("Failed to open mount point: {e}"))?;
+    if !status.success() {
+        return Err(format!("Open command exited with {status}"));
+    }
     Ok(())
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/bin/hf-mount-gui/platform.rs` around lines 138 - 145, The current
open_mount_point uses open_command(&target).spawn() which returns success as
soon as the launcher process starts; instead run the command to completion and
return its exit status so real launcher failures propagate. Replace the spawn()
call with calling .output() (or .status()) on the Command returned by
open_command(&target), map any Io error into the same Err path, then check the
returned ExitStatus: if status.success() return Ok(()), otherwise return Err
with a descriptive message including the exit code and (if using .output())
stderr/stdout text; keep references to open_mount_point, open_target and
open_command so the change is applied in that function.
src/bin/hf-mount-gui/app.rs (1)

916-921: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Keep the forced-unmount fallback off the shutdown thread.

Lines 455-456 already treat platform::unmount_path as potentially blocking on a wedged NFS mount, but on_exit() calls it synchronously here after the 8-second grace period. If that unmount wedges, window close still hangs indefinitely, so this path breaks the bounded-shutdown behavior this method is trying to preserve. Please move the fallback behind a timeout-aware platform helper or a detached cleanup mechanism that cannot block on_exit().

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/bin/hf-mount-gui/app.rs` around lines 916 - 921, The forced unmount call
in on_exit() that directly calls platform::unmount_path(mount_point) can block
shutdown; change this to perform the fallback unmount off the shutdown thread by
submitting it to a detached worker or a timeout-aware helper: either spawn a
detached thread (std::thread::spawn) or use tokio::spawn_blocking to call
platform::unmount_path(mount_point) and return immediately, or wrap the blocking
call in a helper like platform::unmount_path_with_timeout(mount_point, Duration)
that runs the blocking unmount in a separate thread and enforces a timeout;
update the code that checks handle.is_finished() / self.active_mount_point in
on_exit() to call this nonblocking helper instead of calling
platform::unmount_path directly so on_exit() cannot be blocked by a wedged NFS
unmount.
src/nfs.rs (2)

840-884: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Don't report Mounted when HF_MOUNT_SKIP_AUTO_MOUNT skipped mount.exe.

Line 840 intentionally leaves the client mount undone, but Line 876 still emits NfsMountEvent::Mounted and Line 882 still signals readiness. That reports a live mount before one exists, so the GUI/daemon can transition to a mounted/ready state against an unmounted path.

Suggested minimal fix
-    info!("NFS mount active at {}", mount_point_str);
-    on_event(NfsMountEvent::Mounted {
-        mount_point: mount_point_str.to_string(),
-    });
-
-    // Signal the parent process that the mount is live (daemon mode).
-    if let Some(guard) = daemon_guard {
-        guard.notify_ready();
-    }
+    if !skip_auto_mount {
+        info!("NFS mount active at {}", mount_point_str);
+        on_event(NfsMountEvent::Mounted {
+            mount_point: mount_point_str.to_string(),
+        });
+
+        // Signal the parent process that the mount is live (daemon mode).
+        if let Some(guard) = daemon_guard {
+            guard.notify_ready();
+        }
+    } else {
+        info!("NFS server is ready; waiting for a manual mount of {}", mount_point_str);
+    }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/nfs.rs` around lines 840 - 884, The code currently logs
NfsMountEvent::Mounted and calls daemon_guard.notify_ready() unconditionally
even when skip_auto_mount is true (the branch that skips invoking mount.exe),
which reports a live mount that doesn't exist; modify the flow so those two
actions only happen when a real mount was performed—e.g. introduce a boolean
like mount_performed (set true after successful mount in the else branch where
mount_windows_nfs_with_retry returns Some and output.status.success()), and wrap
the calls to on_event(NfsMountEvent::Mounted { mount_point:
mount_point_str.to_string() }) and daemon_guard.notify_ready() in a conditional
that checks mount_performed (or alternatively return early from the
skip_auto_mount branch instead of falling through).

757-766: ⚠️ Potential issue | 🟠 Major

Don’t let shutdown win the mount-vs-cancel race (avoid skipping unmount)
These tokio::select! shutdown arms return early (abort server + vfs_for_shutdown.shutdown()) before reaching the later shutdown/unmount path, so if mount_nfs/mount.nfs/mount.exe has already completed successfully in the same poll, the server/portmapper teardown can happen while the client mount remains.

  • macOS (src/nfs.rs:757-766): wait_for_shutdown can win over command.status(), returning Ok(()) without scheduling spawn_unmount(...).
  • Linux (src/nfs.rs:795-804): same for command.output(), returning Ok(()) without spawn_unmount(...).
  • Windows retry (src/nfs.rs:1354-1356, and the caller handling Ok(None)): wait_for_shutdown can win over command.output(), causing Ok(None) → caller returns Ok(()) without unmount.
Suggested direction
-        let status = tokio::select! {
+        let status = tokio::select! {
+            biased;
             status = command.status() => status?,
             _ = wait_for_shutdown(shutdown.as_ref()) => {
                 server_handle.abort();
                 on_event(NfsMountEvent::ShuttingDown {
                     reason: "stop requested".to_string(),
@@
-        let output = tokio::select! {
+        let output = tokio::select! {
+            biased;
             output = command.output() => output?,
             _ = wait_for_shutdown(shutdown.as_ref()) => return Ok(None),
         };

(Apply the same completion-first behavior to the Windows retry helper as well, so a concurrent successful mount.exe result can’t be treated as cancelled.)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/nfs.rs` around lines 757 - 766, Change the concurrent-selects so a
concurrently-ready mount command always wins and thus the later
unmount/spawn_unmount path runs: in src/nfs.rs at 757-766 (macOS) and 795-804
(Linux) add "biased;" to the tokio::select! and ensure the command arm (status =
command.status() / output = command.output()) is the first arm so it will be
picked when both are ready (leaving the existing server_handle.abort(),
on_event(NfsMountEvent::ShuttingDown { .. }), and vfs_for_shutdown.shutdown()
logic in the shutdown arm unchanged); do the same change for the Windows retry
helper at src/nfs.rs 1354-1356 (add "biased;" and make the command.output() arm
the first arm) so a simultaneous successful mount.exe result isn’t treated as
cancelled and spawn_unmount(...) still runs.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/bin/hf-mount-gui/worker.rs`:
- Around line 153-172: worker_status_is_live currently treats any pid-less
status as live based solely on the heartbeat; update worker_status_is_live to
treat terminal states as dead by checking WorkerStatus.state before using the
heartbeat fallback: if status.pid is None and status.state is
WorkerState::Stopped or WorkerState::Failed then return false (these are written
by mark_worker_stopped() and early startup failure paths), otherwise keep the
existing heartbeat logic that uses updated_at_secs and
WORKER_STATUS_STALE_AFTER_SECS to decide liveness; keep existing
mounted/Platform mount check and worker_process_matches(pid) behavior for
Some(pid).

In `@src/nfs.rs`:
- Around line 1247-1283: Add Linux-only unit tests that exercise the
/proc/mounts parsing and normalization code paths: create tests that call
unescape_proc_mounts and normalize_mount_path (and a small integration-style
test hitting is_mounted by feeding a fake /proc/mounts string if your test
harness can inject it, otherwise test the string-only logic directly) to assert
that octal escapes "\\040", "\\011", "\\012", "\\134" map to " ", tab, newline,
and "\" respectively and that trailing slashes are normalized (e.g., "/foo/" ->
"/foo", "/" stays "/"). Mark the tests with #[cfg(target_os = "linux")] and
include a table-driven set of cases for escapes and trailing-slash behavior so
the regression is covered by CI.

---

Outside diff comments:
In `@src/bin/hf-mount-gui/app.rs`:
- Around line 916-921: The forced unmount call in on_exit() that directly calls
platform::unmount_path(mount_point) can block shutdown; change this to perform
the fallback unmount off the shutdown thread by submitting it to a detached
worker or a timeout-aware helper: either spawn a detached thread
(std::thread::spawn) or use tokio::spawn_blocking to call
platform::unmount_path(mount_point) and return immediately, or wrap the blocking
call in a helper like platform::unmount_path_with_timeout(mount_point, Duration)
that runs the blocking unmount in a separate thread and enforces a timeout;
update the code that checks handle.is_finished() / self.active_mount_point in
on_exit() to call this nonblocking helper instead of calling
platform::unmount_path directly so on_exit() cannot be blocked by a wedged NFS
unmount.

In `@src/bin/hf-mount-gui/platform.rs`:
- Around line 138-145: The current open_mount_point uses
open_command(&target).spawn() which returns success as soon as the launcher
process starts; instead run the command to completion and return its exit status
so real launcher failures propagate. Replace the spawn() call with calling
.output() (or .status()) on the Command returned by open_command(&target), map
any Io error into the same Err path, then check the returned ExitStatus: if
status.success() return Ok(()), otherwise return Err with a descriptive message
including the exit code and (if using .output()) stderr/stdout text; keep
references to open_mount_point, open_target and open_command so the change is
applied in that function.

In `@src/nfs.rs`:
- Around line 840-884: The code currently logs NfsMountEvent::Mounted and calls
daemon_guard.notify_ready() unconditionally even when skip_auto_mount is true
(the branch that skips invoking mount.exe), which reports a live mount that
doesn't exist; modify the flow so those two actions only happen when a real
mount was performed—e.g. introduce a boolean like mount_performed (set true
after successful mount in the else branch where mount_windows_nfs_with_retry
returns Some and output.status.success()), and wrap the calls to
on_event(NfsMountEvent::Mounted { mount_point: mount_point_str.to_string() })
and daemon_guard.notify_ready() in a conditional that checks mount_performed (or
alternatively return early from the skip_auto_mount branch instead of falling
through).
- Around line 757-766: Change the concurrent-selects so a concurrently-ready
mount command always wins and thus the later unmount/spawn_unmount path runs: in
src/nfs.rs at 757-766 (macOS) and 795-804 (Linux) add "biased;" to the
tokio::select! and ensure the command arm (status = command.status() / output =
command.output()) is the first arm so it will be picked when both are ready
(leaving the existing server_handle.abort(),
on_event(NfsMountEvent::ShuttingDown { .. }), and vfs_for_shutdown.shutdown()
logic in the shutdown arm unchanged); do the same change for the Windows retry
helper at src/nfs.rs 1354-1356 (add "biased;" and make the command.output() arm
the first arm) so a simultaneous successful mount.exe result isn’t treated as
cancelled and spawn_unmount(...) still runs.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 63b75688-3ac3-40e0-ac10-c6ac41fd737d

📥 Commits

Reviewing files that changed from the base of the PR and between 92a432f and 4c7873d.

📒 Files selected for processing (5)
  • src/bin/hf-mount-gui/app.rs
  • src/bin/hf-mount-gui/platform.rs
  • src/bin/hf-mount-gui/profile.rs
  • src/bin/hf-mount-gui/worker.rs
  • src/nfs.rs

Comment thread src/bin/hf-mount-gui/worker.rs
Comment thread src/nfs.rs
A review round on the GUI/NFS rewrite surfaced several ways a wedged or
recycled NFS mount could hang the UI, orphan a mount, or misreport state.

GUI (hf-mount-gui):
- on_exit now runs the forced fallback unmount on a detached thread with a
  bounded wait, so window close stays bounded even if umount wedges.
- Startup reconcile is non-blocking (heartbeat-only). The full liveness
  check stats the mount and must never run before the first frame; the
  poller re-confirms on its own thread within one interval.
- worker_status_is_live treats terminal states as dead and no longer trusts
  the Windows metadata-only mount probe as authoritative (a leftover
  directory from a crashed worker could pass it); it falls through to the
  PID check there instead.
- Post-stop cleanup only unmounts a path confirmed to be our loopback NFS
  export, so the race cleanup can't detach an unrelated pre-existing mount.

NFS backend (src/nfs.rs):
- biased mount-command selects so a mount that completed in the same poll
  as a stop wins; the wait loop then unmounts it instead of the server
  tearing down with the client mount left behind.
- HF_MOUNT_SKIP_AUTO_MOUNT no longer emits Mounted or signals readiness.
- Add is_loopback_nfs_mount plus Linux /proc/mounts parsing regression
  tests (octal-escape decode, trailing-slash normalization).

Sidecar (hf-mount-fuse-sidecar): convert a last-resort panic in the mount
thread into an error marker, so a panic before the ready/error file is
written can't hang pod readiness (the readiness wait loop has no timeout).

https://claude.ai/code/session_01D3AdfdaNzP6eBm3seWGuJP
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@ArturLauche
ArturLauche merged commit 97194e5 into main Jun 13, 2026
9 checks passed
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