Skip to content

fix: close relayfile mount conflict and lifecycle gaps - #393

Merged
khaliqgant merged 9 commits into
mainfrom
fix/mount-conflict-credential-background
Aug 4, 2026
Merged

fix: close relayfile mount conflict and lifecycle gaps#393
khaliqgant merged 9 commits into
mainfrom
fix/mount-conflict-credential-background

Conversation

@khaliqgant

@khaliqgant khaliqgant commented Aug 3, 2026

Copy link
Copy Markdown
Member

Summary

Three separate commits address the three reproduced mount defects from the 2026-08-03 resume brief.

  • 23ee9f1 preserves same-path edits when a WebSocket update beats the local watcher debounce
  • 3e85f16 falls back to saved login credentials when delegated resolution fails, without overriding a healthy delegated session
  • de42a9c prevents mount --background from refusing its transient launcher or its own pidfile entry

Validation

Bug 1:

  • Pre-fix and post-fix real cross-machine race via a pre-warmed SSH ControlMaster between this Mac and finn-mini against self-hosted durable-local
  • Losing edit is preserved in .relay/conflicts/fixed-ws.md.rev_5.local and both mirrors converge
  • Duplicate/stale remote-base events preserve the single local edit without creating a false conflict; oversized local drift remains preserved and surfaces as writeback-skipped
  • go test -race targeted near-simultaneous, WebSocket-debounce, duplicate-base, and oversized-file tests

Bug 2:

  • Real freshly built CLI: login, mount --once, and status with no repeated server/token flags and no agent-relay executable on PATH
  • Saved credentials hash is identical before and after mount/status
  • Duplicate workspace names resolve by exact ID or token claim, return the canonical catalog ID when the claim matches relayWorkspaceId, and fail closed when genuinely ambiguous
  • Existing stale-plain-credential/delegated-session precedence test remains unchanged and green

Bug 3:

  • Pre-fix clean launch reproduced two competing PIDs: the transient parent and the child itself
  • Post-fix clean mount --background registers, reports running, and stops cleanly on both this Mac and finn-mini
  • Regression coverage includes both independent discovery guards and a real spawnBackgroundMountProcess re-exec test
  • sf-mini was unreachable with the available SSH key

Full local gate: go test ./... -count=1 passed after all implementation changes. Complete race suites passed for internal/mountsync and cmd/relayfile-cli. All required GitHub checks, including E2E, are green.

Operational note: the Trail executable was unavailable both globally and in node_modules/.bin, so this run could not record or compact a trajectory. The existing .trajectories store remains present and intact for a later CLI-enabled run.

Independent review approved all three commits. Draft PR; do not merge.

@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@khaliqgant, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 22 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: df094aa5-b993-4890-bc2e-9ffc336c1839

📥 Commits

Reviewing files that changed from the base of the PR and between 860ba56 and 1f358c6.

📒 Files selected for processing (3)
  • cmd/relayfile-cli/main.go
  • cmd/relayfile-cli/main_test.go
  • internal/mountsync/assessment_propagation_test.go
📝 Walkthrough

Walkthrough

The CLI adds legacy credential fallback, canonical workspace resolution, duplicate-name disambiguation, and improved daemon discovery. Mount synchronization now rejects stale reads, preserves local edits, and records conflicts for concurrent divergence.

Changes

CLI credential, workspace, and daemon behavior

Layer / File(s) Summary
Credential and workspace resolution
cmd/relayfile-cli/main.go, cmd/relayfile-cli/main_test.go
Mount and workspace commands fall back to saved credentials. Workspace lookup canonicalizes IDs and resolves duplicate names with token claims.
Daemon discovery and flag parsing
cmd/relayfile-cli/main.go, cmd/relayfile-cli/main_test.go
Daemon discovery excludes the caller and transient background launchers. Boolean flags accept bare and explicit values. Subprocess tests cover registration and shutdown.

Mount synchronization conflict handling

Layer / File(s) Summary
Remote edit assessment and conflict handling
internal/mountsync/syncer.go, internal/mountsync/assessment_propagation_test.go
Remote application compares local, remote, and tracked-base hashes. Stale reads preserve local edits. Concurrent divergence creates one conflict artifact.
Oversized file preservation
internal/mountsync/mount_root_clobber_test.go
Tests verify that oversized local files remain unchanged and report dirty, writeback-skipped state.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CLI
  participant Credentials
  participant Catalog
  participant RelayfileAPI
  CLI->>Credentials: Load delegated credentials
  Credentials-->>CLI: Return delegated or legacy token
  CLI->>Catalog: Resolve workspace ID
  Catalog-->>CLI: Return canonical workspace record
  CLI->>RelayfileAPI: Send authenticated request
Loading
sequenceDiagram
  participant WebSocket
  participant Syncer
  participant LocalWatcher
  participant FileState
  WebSocket->>Syncer: Deliver remote file event
  Syncer->>FileState: Snapshot tracked state
  Syncer->>WebSocket: Read remote file
  LocalWatcher->>FileState: Advance state after local write
  Syncer->>FileState: Discard stale response or apply conflict result
Loading

Possibly related PRs

Suggested reviewers: miyaontherelay, kjgbot, willwashburn

Poem

A rabbit checks the token store,
Then maps each workspace to its door.
Stale reads leave local edits bright,
True conflicts gain their marked write.
Daemons skip their own PID.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the pull request's main fixes for mount conflicts and lifecycle gaps.
Description check ✅ Passed The description directly covers the three mount defects, implementation changes, tests, and validation results.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ 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 fix/mount-conflict-credential-background

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.

@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown

Relayfile Eval Review

Run: .relayfile/evals/runs/2026-08-04T07-16-59-721Z-HEAD-provider
Mode: provider
Git SHA: 67ac18b

Passed: 4 | Needs human: 0 | Reviewable: 0 | Missing output: 0 | Failed: 0 | Skipped: 0

Human Review Cases

No reviewable human-review cases captured Relayfile output.

@khaliqgant
khaliqgant force-pushed the fix/mount-conflict-credential-background branch from 3b9bc4e to de42a9c Compare August 3, 2026 19:20
@khaliqgant
khaliqgant marked this pull request as ready for review August 3, 2026 19:55
@cursor

cursor Bot commented Aug 3, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@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: de42a9c7fc

ℹ️ 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 cmd/relayfile-cli/main.go
Comment on lines 6501 to +6502
if berr != nil {
return fmt.Errorf("resolve delegated relayfile credentials: %w", berr)
}
delegatedCredsPath = path
bundle, berr = refreshDelegatedCredentials(path, bundle, false)
if berr != nil {
return fmt.Errorf("refresh delegated relayfile credentials: %w", berr)
}
canonicalWorkspaceID = bundle.Workspace()
if requestedWorkspace != "" && !workspaceRequestMatchesDelegatedCredentials(requestedWorkspace, canonicalWorkspaceID) {
return fmt.Errorf(
"relayfile mount without --token uses delegated relayfile workspace %s; pass --token for explicit workspace %q or re-bootstrap delegated credentials for that workspace",
canonicalWorkspaceID,
requestedWorkspace,
)
tokenValue = strings.TrimSpace(creds.Token)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Fail when an explicit delegated credential file is unusable

When --creds-file or RELAYFILE_MOUNT_CREDS_FILE explicitly selects a missing, malformed, or otherwise unusable delegated bundle and saved login credentials also exist, this branch silently discards the delegated-credential error and mounts with the saved token instead. This violates the explicit credential selection (the standalone mount command treats the credentials file as taking precedence and fails if it cannot be read) and can send setup/mount requests using a token from another workspace or server; only use this fallback when no delegated credentials path was explicitly supplied.

Useful? React with 👍 / 👎.

@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: 1

🧹 Nitpick comments (5)
cmd/relayfile-cli/main_test.go (1)

2269-2281: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Isolate HOME and Relayfile environment variables in this test.

The neighboring tests call t.Setenv("HOME", t.TempDir()) and clearRelayfileEnv(t). This test omits both. runningMountDaemons can read state outside the temp directory, so the result may depend on the developer machine or CI image.

♻️ Proposed change
 func TestRunningMountDaemonsExcludesCallerPIDFromPIDFile(t *testing.T) {
+	t.Setenv("HOME", t.TempDir())
+	clearRelayfileEnv(t)
 	localDir := t.TempDir()
🤖 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 `@cmd/relayfile-cli/main_test.go` around lines 2269 - 2281, Update
TestRunningMountDaemonsExcludesCallerPIDFromPIDFile to isolate its environment
before invoking the daemon-discovery logic: set HOME to a temporary directory
and call clearRelayfileEnv(t), matching the neighboring tests. Keep the existing
PID state setup and assertions unchanged.
cmd/relayfile-cli/main.go (3)

6502-6521: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicated delegated-to-legacy credential fallback discards the delegated error. Both call sites repeat the same four-step fallback and drop the delegated error when a saved token exists. Extract one helper that returns the resolved token and server, and log the discarded error inside it.

  • cmd/relayfile-cli/main.go#L6502-L6521: replace the two inline fallback branches with the shared helper, and keep the serverProvided guard by passing it in.
  • cmd/relayfile-cli/main.go#L7127-L7147: replace the two inline fallback branches with the same helper, and set directToken and credsFile from its result.
🤖 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 `@cmd/relayfile-cli/main.go` around lines 6502 - 6521, Extract the duplicated
delegated-to-legacy credential fallback into a shared helper that accepts the
server-provided guard, logs the discarded delegated error, and returns the
resolved token and server. In cmd/relayfile-cli/main.go lines 6502-6521, replace
both inline fallback branches with this helper while preserving serverProvided
behavior; in lines 7127-7147, use the same helper and assign its results to
directToken and credsFile.

11503-11519: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

Continue scanning after an explicit boolean value.

The = branch returns on the first matching field. For --background=false --background, the function returns false, but Go's flag package applies the last occurrence and yields true. Track the value and return it after the loop instead.

♻️ Proposed change
 func commandHasEnabledBoolFlag(fields []string, name string) bool {
 	longFlag := "--" + name
 	shortFlag := "-" + name
+	enabled := false
 	for _, field := range fields {
 		if field == longFlag || field == shortFlag {
-			return true
+			enabled = true
+			continue
 		}
 		if strings.HasPrefix(field, longFlag+"=") || strings.HasPrefix(field, shortFlag+"=") {
 			value := strings.TrimSpace(strings.TrimPrefix(strings.TrimPrefix(field, longFlag+"="), shortFlag+"="))
 			if value == "" {
-				return true
+				enabled = true
+				continue
 			}
 			parsed, err := strconv.ParseBool(value)
-			return err != nil || parsed
+			enabled = err != nil || parsed
 		}
 	}
-	return false
+	return enabled
 }
🤖 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 `@cmd/relayfile-cli/main.go` around lines 11503 - 11519, Update
commandHasEnabledBoolFlag to retain the latest matching boolean flag value
instead of returning from the `=` branch immediately. Continue scanning all
fields so later occurrences override earlier ones, matching Go flag behavior;
preserve the existing handling for empty values and parse errors, then return
the tracked result after the loop.

10672-10678: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Silence the nilerr finding and document the soft failure.

catalogWorkspaceIDForRequest returns nil after loadWorkspaceCatalog fails. golangci-lint reports this as a nilerr error, so the lint step fails. The behavior looks intentional: a missing or unreadable catalog must not block resolution, because callers fall back to the raw value. Make that intent explicit.

♻️ Proposed change
 func catalogWorkspaceIDForRequest(name, token string) (string, bool, error) {
 	catalog, err := loadWorkspaceCatalog()
 	if err != nil {
-		return "", false, nil
+		// A missing or unreadable catalog cannot canonicalize the request.
+		// Callers fall back to the requested value, so this is not fatal.
+		return "", false, nil //nolint:nilerr // soft-fail: no catalog means no canonical ID
 	}
 	return catalogWorkspaceIDFromCatalogForRequest(catalog, name, token)
 }
🤖 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 `@cmd/relayfile-cli/main.go` around lines 10672 - 10678, Update
catalogWorkspaceIDForRequest to document and explicitly preserve the intentional
soft-failure behavior when loadWorkspaceCatalog returns an error: return no
workspace ID without propagating the catalog-loading error, while keeping
successful catalog resolution unchanged. Make the non-nil error handling
explicit so golangci-lint no longer reports nilerr.

Source: Linters/SAST tools

internal/mountsync/syncer.go (1)

6049-6086: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add test coverage for the conflict/preserve race on a ReadOnly path.

Both new branches require canWrite to be true. Before overwriting divergent local content, the syncer compares local and remote hashes with the tracked base. It preserves local edits for duplicate or stale remote events whose content still matches the base, while concurrent divergence creates a conflict artifact using the tracked revision. When canWrite is false, neither branch runs, so shouldWrite stays true and the remote content silently replaces local content, even if both sides diverged from the tracked base. No conflict artifact is written in that case.

This is likely intentional, since a ReadOnly path should not have legitimate local edits. Confirm this is the desired behavior, and add a test that exercises the same race on a ReadOnly path (mirroring TestAssessSameFileWebSocketBeatsDebouncedWatcher) to lock in the intended outcome.

🤖 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 `@internal/mountsync/syncer.go` around lines 6049 - 6086, Confirm the intended
ReadOnly behavior and add a regression test mirroring
TestAssessSameFileWebSocketBeatsDebouncedWatcher for the same
debounced-local-edit versus WebSocket race. Configure the path so canWrite is
false and both local and remote content diverge from the tracked base, then
assert the remote content replaces the local content, no conflict artifact is
created, and the path remains consistent with ReadOnly semantics.
🤖 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 `@cmd/relayfile-cli/main_test.go`:
- Around line 2710-2724: Move the background child cleanup in the test around
spawnBackgroundMountProcess to immediately after it returns, before validating
structured, Registered, and PID state. Guard cleanup with state.PID > 0 so
invalid pidfile data does not trigger an invalid process lookup, while ensuring
any registered child is stopped even when the subsequent validation calls
t.Fatalf.

---

Nitpick comments:
In `@cmd/relayfile-cli/main_test.go`:
- Around line 2269-2281: Update
TestRunningMountDaemonsExcludesCallerPIDFromPIDFile to isolate its environment
before invoking the daemon-discovery logic: set HOME to a temporary directory
and call clearRelayfileEnv(t), matching the neighboring tests. Keep the existing
PID state setup and assertions unchanged.

In `@cmd/relayfile-cli/main.go`:
- Around line 6502-6521: Extract the duplicated delegated-to-legacy credential
fallback into a shared helper that accepts the server-provided guard, logs the
discarded delegated error, and returns the resolved token and server. In
cmd/relayfile-cli/main.go lines 6502-6521, replace both inline fallback branches
with this helper while preserving serverProvided behavior; in lines 7127-7147,
use the same helper and assign its results to directToken and credsFile.
- Around line 11503-11519: Update commandHasEnabledBoolFlag to retain the latest
matching boolean flag value instead of returning from the `=` branch
immediately. Continue scanning all fields so later occurrences override earlier
ones, matching Go flag behavior; preserve the existing handling for empty values
and parse errors, then return the tracked result after the loop.
- Around line 10672-10678: Update catalogWorkspaceIDForRequest to document and
explicitly preserve the intentional soft-failure behavior when
loadWorkspaceCatalog returns an error: return no workspace ID without
propagating the catalog-loading error, while keeping successful catalog
resolution unchanged. Make the non-nil error handling explicit so golangci-lint
no longer reports nilerr.

In `@internal/mountsync/syncer.go`:
- Around line 6049-6086: Confirm the intended ReadOnly behavior and add a
regression test mirroring TestAssessSameFileWebSocketBeatsDebouncedWatcher for
the same debounced-local-edit versus WebSocket race. Configure the path so
canWrite is false and both local and remote content diverge from the tracked
base, then assert the remote content replaces the local content, no conflict
artifact is created, and the path remains consistent with ReadOnly semantics.
🪄 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: CHILL

Plan: Pro Plus

Run ID: aa6e201e-45e8-4b83-933e-1be926daa1c4

📥 Commits

Reviewing files that changed from the base of the PR and between ea67a73 and de42a9c.

📒 Files selected for processing (5)
  • cmd/relayfile-cli/main.go
  • cmd/relayfile-cli/main_test.go
  • internal/mountsync/assessment_propagation_test.go
  • internal/mountsync/mount_root_clobber_test.go
  • internal/mountsync/syncer.go

Comment on lines +2710 to +2724
if err := spawnBackgroundMountProcess(args, []string{"/"}, localDir, pidFile, logFile, mountscope.LayoutExact); err != nil {
logBytes, _ := os.ReadFile(logFile)
t.Fatalf("spawnBackgroundMountProcess failed: %v\nlog:\n%s", err, logBytes)
}
state, structured := readDaemonPIDStateFile(pidFile)
if !structured || !state.Registered || state.PID <= 0 {
t.Fatalf("background child did not register: structured=%v state=%+v", structured, state)
}
t.Cleanup(func() {
if processAlive(state.PID) {
if process, err := os.FindProcess(state.PID); err == nil {
_ = forceDaemonStop(process)
}
}
})

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Inspect spawnBackgroundMountProcess for a registration wait.
set -euo pipefail

fd -t f 'main.go' cmd/relayfile-cli | while IFS= read -r file; do
  ast-grep run --lang go \
    --pattern 'func spawnBackgroundMountProcess($$$) $$$ { $$$ }' "$file" || true
done

rg -nP --type=go -C4 'spawnBackgroundMountProcessFn|func spawnBackgroundMountProcess|readDaemonPIDStateFile|waitForDaemonRegistration'

Repository: AgentWorkforce/relayfile

Length of output: 4023


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Map and inspect the relevant functions around spawnBackgroundMountProcess and waitForBackgroundMountRegistration.
fd -t f 'main.go' cmd/relayfile-cli 2>/dev/null | while IFS= read -r file; do
  ast-grep run --lang go --pattern 'func waitForBackgroundMountRegistration($$$) $$$ { $$$ }' "$file" || true
  ast-grep run --lang go --pattern 'func readDaemonPIDStateFile($$$) $$$ { $$$ }' "$file" || true
done

printf '\n--- spawnBackgroundMountProcess and related wait code ---\n'
sed -n '12736,12805p' cmd/relayfile-cli/main.go

printf '\n--- waitForBackgroundMountRegistration implementation ---\n'
rg -n --type=go -C 12 'func waitForBackgroundMountRegistration' cmd/relayfile-cli/main.go

printf '\n--- readDaemonPIDStateFile implementation ---\n'
rg -n --type=go -C 8 'func readDaemonPIDStateFile' cmd/relayfile-cli/main.go

printf '\n--- processAlive implementation ---\n'
rg -n --type=go -C 6 'func processAlive|processAlive\(' cmd/relayfile-cli/main.go

printf '\n--- TestSpawnBackgroundMountProcessRegistersRealChild surrounding code ---\n'
sed -n '2674,2745p' cmd/relayfile-cli/main_test.go

Repository: AgentWorkforce/relayfile

Length of output: 13030


Register the background-mount child cleanup before asserting on the pidfile.

spawnBackgroundMountProcess already waits for daemon state registration, so the immediate pidfile read is not racy. However, t.Cleanup is registered after the assertion at lines 2715-2717. If the assertion fails and calls t.Fatalf, the spawned child is never stopped. Register the cleanup with a guarded state.PID > 0 check before any t.Fatalf for pidstate validation.

🤖 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 `@cmd/relayfile-cli/main_test.go` around lines 2710 - 2724, Move the background
child cleanup in the test around spawnBackgroundMountProcess to immediately
after it returns, before validating structured, Registered, and PID state. Guard
cleanup with state.PID > 0 so invalid pidfile data does not trigger an invalid
process lookup, while ensuring any registered child is stopped even when the
subsequent validation calls t.Fatalf.

@cubic-dev-ai cubic-dev-ai 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.

All reported issues were addressed across 5 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread internal/mountsync/syncer.go
Comment thread cmd/relayfile-cli/main_test.go
Comment thread cmd/relayfile-cli/main_test.go
@khaliqgant
khaliqgant marked this pull request as draft August 3, 2026 20:12
@khaliqgant
khaliqgant marked this pull request as ready for review August 4, 2026 06:37

@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: 1

Caution

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

⚠️ Outside diff range comments (1)
internal/mountsync/syncer.go (1)

6064-6101: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Persist the remote revision for content-equivalent remote writes.

At internal/mountsync/syncer.go lines 6087-6093, the path preserves local bytes when remote content matches the tracked hash, but it does not update tracked.Revision. A later writeback can send the old baseRevision, causing an existing conflict artifact and losing the remote progress. Move revision advancement into this branch and add the base rev_1, remote rev_2 same-contents, divergent-local case.

🤖 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 `@internal/mountsync/syncer.go` around lines 6064 - 6101, The
content-equivalent remote-write branch in the tracked-entry apply logic must
also persist the incoming remote revision. Update the branch guarded by
!tracked.Dirty and !remoteDivergedFromBase to assign tracked.Revision from the
remote revision before suppressing the write, while preserving the local bytes;
add coverage for base rev_1, remote rev_2 with identical content, and divergent
local content, verifying later writeback uses rev_2.
🤖 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 `@internal/mountsync/assessment_propagation_test.go`:
- Around line 562-564: Bound the eventResult wait in the test around
applyWebSocketEvent so it cannot block indefinitely. Replace the direct channel
receive with a local timeout mechanism that fails the test promptly if
completion does not arrive, while preserving the existing
duplicate-websocket-apply error assertion when eventResult returns.

---

Outside diff comments:
In `@internal/mountsync/syncer.go`:
- Around line 6064-6101: The content-equivalent remote-write branch in the
tracked-entry apply logic must also persist the incoming remote revision. Update
the branch guarded by !tracked.Dirty and !remoteDivergedFromBase to assign
tracked.Revision from the remote revision before suppressing the write, while
preserving the local bytes; add coverage for base rev_1, remote rev_2 with
identical content, and divergent local content, verifying later writeback uses
rev_2.
🪄 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: CHILL

Plan: Pro Plus

Run ID: 9b99fa9f-9be7-40d5-8e2e-3914b1bf5bda

📥 Commits

Reviewing files that changed from the base of the PR and between de42a9c and 860ba56.

📒 Files selected for processing (3)
  • cmd/relayfile-cli/main_test.go
  • internal/mountsync/assessment_propagation_test.go
  • internal/mountsync/syncer.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • cmd/relayfile-cli/main_test.go

Comment thread internal/mountsync/assessment_propagation_test.go Outdated

@cubic-dev-ai cubic-dev-ai 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.

All reported issues were addressed across 5 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread internal/mountsync/assessment_propagation_test.go
Comment thread internal/mountsync/assessment_propagation_test.go Outdated
@khaliqgant
khaliqgant merged commit a4e8505 into main Aug 4, 2026
10 checks passed
@khaliqgant
khaliqgant deleted the fix/mount-conflict-credential-background branch August 4, 2026 08:35
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.

1 participant