Repository navigation
Re-send repo paths when repos.json changes under a running daemon - #959
Conversation
The watcher compares the file against the fingerprint the last successful send read, not a baseline primed at start, so a write between registration and the first tick is not lost and a failed send retries by itself. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
PR Summary by QodoRefresh daemon repo paths when repos.json changes
AI Description
Diagram
High-Level Assessment
Files changed (10)
|
Code Review by Qodo
1.
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 46f3f50f3c
ℹ️ 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".
| public RepoStoreFingerprint? Fingerprint() { | ||
| try { | ||
| var info = new FileInfo(StorePath); | ||
| return info.Exists ? new RepoStoreFingerprint(info.Length, info.LastWriteTimeUtc.Ticks) : null; |
There was a problem hiding this comment.
Hash repo contents to detect same-size writes
On filesystems with coarse timestamp resolution, such as some NFS or FAT-backed home directories, two writes between the watcher's three-second polls can have the same LastWriteTimeUtc; replacing one path with an equal-length path also preserves the file size. The fingerprints then compare equal, so TickAsync skips the update indefinitely even though repos.json changed. Include content identity, such as a hash, rather than relying solely on size and mtime.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in 89034ef. The fingerprint is now a SHA-256 of the file's bytes, read with FileShare.Delete so a save in another process can still rename over it mid-read. Fingerprint_TellsApartSameLengthWritesWithTheSameTimestamp writes two same-length contents with an identical LastWriteTimeUtc and asserts the fingerprints differ; Fingerprint_IgnoresATouchThatLeavesTheContentAlone pins the other direction, so a bare touch no longer triggers a send.
The server runs one client's hub invocations in parallel, so an older repo list can be processed after a newer one while the newer fingerprint is recorded last; and a same-length rewrite inside the filesystem's timestamp resolution reads as no change under size and mtime. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
AI-838 — no GitHub issue exists for this one; the Linear issue predates the GitHub-first convention.
What & why
kcap repos addwritesrepos.jsonand exits, and the daemon read that file only at registration and after its own launches, so a repo added from a terminal never reached the launch dialog until the daemon restarted. The daemon now polls a content hash of the file (one read of a small file every 3 s) and re-sends its repo paths through the existingDaemonUpdateRepoPathshub method when the file differs from the one the last send read. Polling covers every writer — the CLI, the desktop app, the daemon's own launch path, a hand edit — without any of them needing to know whether a daemon is running.Where to look
The watcher compares against the fingerprint recorded by the last successful send, not a baseline it primes at start. That closes the gap between registration reading the file and the watcher's first tick, and makes a failed send retry on the next tick with no extra state. The fingerprint is taken before the read it pairs with, so a write landing mid-read still reads as a change afterwards. Registration and the update share the connection's existing lock across snapshot-and-send, because the server runs one client's invocations in parallel and two overlapping sends could otherwise land in the opposite order to the fingerprints they record.
Verification
Three mutations against the new tests, each restored afterwards:
RepoStoreWatcher.TickAsyncNothing_is_sent_until_the_daemon_is_registered)A_send_carries…records_the_file_it_read,The_watcher_sends…exactly_once)Overlapping_sends_run_one_at_a_time)Full suites on this branch:
The one daemon failure is unrelated to this change:
Installed_codex_schema_matches_the_vendored_pinfails because this machine's Codex is 0.154.0 against a pin from 0.147.0.dotnet publish src/Capacitor.Cli/Capacitor.Cli.csproj -c Release 2>&1 | grep -E 'IL[23][01][0-9]{2}'— no output.🤖 Generated with Claude Code