Skip to content

Files tree does not update for changes made outside the app #4

Description

@Francois3d

Problem

After #1, the Files tree updates for changes the app makes. Changes made outside the app — touch in a terminal, a file added in Finder, a build writing output — still do not appear until the panel remounts or its 30s staleness window lapses.

Scoping in #2 established that the server-side data is already live. The FileFinder index picks up external creates and deletes on its own in ~100ms with no refresh call. The only missing piece is that the server never learns the index moved, because FileFinder exposes no change callback, so #1's signal is never published.

Full evidence and the rejected alternatives are in the scoping comment on #2. Summary of what that measured on this repo (17,701 entries, populated node_modules, active .git):

  • external create visible without scanFiles: ~103ms; external delete: ~104ms
  • getScanProgress().scannedFilesCount never moves — not a usable signal
  • mixedSearch("", { pageSize: 1 }).totalMatched tracks add/delete exactly, costs ~0.5ms (vs 350ms for a full list)
  • node_modules / .git write churn: 0/30 samples moved the count; idle repo over 20s: 0 changes

Scope

Publish #1's existing signal when the index changes underneath us, detected by a cheap count poll. No new filesystem watcher, no new ignore list, no rescan.

Implementation sketch

All server-side. Contracts, auth, and the client are untouched — #1 already shipped subscribeProjectEntryChanges and the invalidate line on listEntries.

  1. apps/server/src/workspace/WorkspaceSearchIndex.ts — expose a cheap entryCount() on the service, backed by finder.mixedSearch("", { pageSize: 1 }).totalMatched. pageSize: 1 is load-bearing: it returns the total without materialising the page.
  2. apps/server/src/workspace/WorkspaceEntries.ts — while at least one client is subscribed for a workspace, run a poll fibre at a fixed interval, compare entryCount() to the last observed value, and publish the existing coarse signal on change. Reuse the PubSub keyed by normalised workspace root that Files tree does not update live when files are added or deleted #1 added; do not add a second channel.
  3. Lifetime — the fibre is scoped to the subscription, not to the process. Last unsubscribe stops it. The index's own 15-minute idle TTL is unchanged; an active subscription counts as active use, which is correct.

Suggested interval 1s (0.05% of one core per subscribed workspace). This is the one number worth a maintainer's opinion — 2s halves an already negligible cost and still feels instant for a file tree.

Acceptance criteria

  • With the Files panel open and untouched, touch test.txt from a terminal makes the file appear in the tree without remounting or reloading.
  • Deleting that file from a terminal removes it the same way.
  • With the panel open on a real repo and the workspace idle, no signal is published — verified over at least 20s.
  • node_modules and .git write churn publishes no signal.
  • No new filesystem watcher is introduced, and refresh / scanFiles is not called by this change.
  • Web verified at minimum; mobile and desktop follow through the shared listEntries atom.

Known and accepted gaps

  • A rename, or a balanced add+delete, leaves the count unchanged and publishes nothing. The 30s client staleness window still catches it; in-app renames still go through refresh. This narrows the gap rather than closing it — say so in the PR body rather than claiming external changes are fully live.
  • Content-only edits do not move the count. Intended: the tree does not care, and subscribeProjectFileChanges already covers open-file contents.

Out of scope

Upstream

The clean fix is a change callback on FileFinder instead of a poll. Worth raising with ff-labs; this ticket is the bridge until then.

Tests

  • A WorkspaceEntries test asserting the signal is published when the underlying count changes, and not when it does not.
  • Drive it off the receipt/PubSub, not a sleep.

Conventions

Read docs/internals/code-conventions.md first, and .macroscope/check-run-agents/effect-service-conventions.md before touching server services.

Depends on

#1 (landed) — this publishes on the channel that ticket built.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestready-for-agentFully specified, ready for an AFK agent

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions