Skip to content

Restore FileSystem.watch recursive control - #6705

Merged
tim-smart merged 5 commits into
Effect-TS:mainfrom
tylergibbs1:agent/restore-watch-recursion
Jul 29, 2026
Merged

Restore FileSystem.watch recursive control#6705
tim-smart merged 5 commits into
Effect-TS:mainfrom
tylergibbs1:agent/restore-watch-recursion

Conversation

@tylergibbs1

@tylergibbs1 tylergibbs1 commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Summary

  • restore the v3 WatchOptions API on FileSystem.watch
  • forward the option through WatchBackend and the Node/Deno native implementations
  • default omitted or false options to non-recursive watching
  • add Node regression coverage for both direct-child and recursive behavior
  • add a patch changeset for the affected packages

Why

The v4 migration removed the watch options and hard-coded recursive watching in the Node-compatible implementation used by Node and Bun. That silently widened existing watchers to entire directory trees and could trigger extra rebuilds or feedback loops.

Root cause

The established option from #5174 was dropped while the filesystem API moved into effect, and native watchers were changed to recursive: true instead of forwarding caller intent.

Impact

fs.watch(path) and fs.watch(path, { recursive: false }) again observe only direct children. Passing { recursive: true } opts into subtree events.

Verification

  • focused regression tests added for recursive: false and recursive: true
  • branch diff audited against current main
  • GitHub Check and Snapshot workflows are awaiting the repository's required approval for forked workflows; no jobs have run yet

Closes #6698

Summary by CodeRabbit

  • New Features
    • Extended FileSystem.watch to accept optional WatchOptions (including recursive?: boolean) and threaded options through the Node and Deno implementations.
  • Bug Fixes
    • Restored recursive handling for filesystem watching; non-recursive watching is now the default when recursive isn’t specified.
  • Tests
    • Added/expanded Node filesystem watch tests to confirm first detected changes for recursive: true vs non-recursive (including the default).
  • Chores
    • Added a changeset for patch-level release publishing.

@github-project-automation github-project-automation Bot moved this to Discussion Ongoing in PR Backlog Jul 28, 2026
@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: cb7d27e2-4380-4d00-8c4e-fd0a5bd82d58

📥 Commits

Reviewing files that changed from the base of the PR and between d67acc0 and a15fc71.

📒 Files selected for processing (1)
  • packages/platform-node-shared/test/NodeFileSystem.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/platform-node-shared/test/NodeFileSystem.test.ts

📝 Walkthrough

Walkthrough

Restores optional recursive control to FileSystem.watch and WatchBackend.register, propagates it through Deno and Node implementations with non-recursive defaults, adds Node behavior tests, and records patch releases.

Changes

Filesystem watch options

Layer / File(s) Summary
Watch API contract
packages/effect/src/FileSystem.ts
Adds exported WatchOptions, updates FileSystem.watch, and extends WatchBackend.register to accept optional watch options.
Platform watch propagation
packages/platform-deno/src/DenoFileSystem.ts, packages/platform-node-shared/src/NodeFileSystem.ts
Passes recursive through backend and native watcher paths, defaulting to false.
Watch behavior validation and release metadata
packages/platform-node-shared/test/NodeFileSystem.test.ts, .changeset/wise-files-watch.md
Tests direct-only, default, and recursive events and records patch releases for the affected packages.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant FileSystem
  participant NodeFileSystem
  participant NativeWatcher
  Caller->>FileSystem: watch(path, { recursive })
  FileSystem->>NodeFileSystem: forward watch options
  NodeFileSystem->>NativeWatcher: configure recursive watcher
  NativeWatcher-->>FileSystem: emit filesystem event
  FileSystem-->>Caller: emit WatchEvent
Loading

Suggested labels: bug

🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The PR restores WatchOptions through the core API and Node watch path, preserves non-recursive defaults, and adds tests for recursive and non-recursive behavior.
Out of Scope Changes check ✅ Passed The Deno update, tests, and changeset all support the watch fix and release, with no clear unrelated code changes introduced.

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

@changeset-bot

changeset-bot Bot commented Jul 28, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: a15fc71

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 29 packages
Name Type
@effect/platform-deno Patch
@effect/platform-node-shared Patch
effect Patch
@effect/opentelemetry Patch
@effect/platform-browser Patch
@effect/platform-bun Patch
@effect/platform-node Patch
@effect/vitest Patch
@effect/ai-anthropic Patch
@effect/ai-openai-compat Patch
@effect/ai-openai Patch
@effect/ai-openrouter Patch
@effect/atom-react Patch
@effect/atom-solid Patch
@effect/atom-vue Patch
@effect/sql-clickhouse Patch
@effect/sql-d1 Patch
@effect/sql-libsql Patch
@effect/sql-mssql Patch
@effect/sql-mysql2 Patch
@effect/sql-pg Patch
@effect/sql-pglite Patch
@effect/sql-sqlite-bun Patch
@effect/sql-sqlite-do Patch
@effect/sql-sqlite-node Patch
@effect/sql-sqlite-react-native Patch
@effect/sql-sqlite-wasm Patch
@effect/docgen Patch
@effect/openapi-generator Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@effect-slopcop effect-slopcop Bot added 4.0 bug Something isn't working labels Jul 28, 2026
@tim-smart
tim-smart marked this pull request as ready for review July 28, 2026 20:34
@tim-smart tim-smart removed the bug Something isn't working label Jul 28, 2026
@coderabbitai coderabbitai Bot added the bug Something isn't working label Jul 28, 2026

Copy link
Copy Markdown
Contributor Author

Fixed the actionable Check failures in 977d23e: updated the new tests to the v4 Effect.forkChild API and moved the extended watch documentation under a Details section for the JSDoc linter. A fresh CI run should start from this push.

@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 (1)
packages/platform-node-shared/test/NodeFileSystem.test.ts (1)

19-22: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Cover the omitted-options default.

This verifies only recursive: false; add a case with fs.watch(root) and confirm nested changes remain excluded, since omitted options are also required to default to non-recursive watching.

🤖 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 `@packages/platform-node-shared/test/NodeFileSystem.test.ts` around lines 19 -
22, Add a test alongside the existing fs.watch coverage that calls
fs.watch(root) without options and verifies changes in nested paths are not
reported, preserving the expected non-recursive default behavior.
🤖 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 `@packages/platform-node-shared/test/NodeFileSystem.test.ts`:
- Around line 19-24: Add an explicit readiness barrier after starting the
watcher in both tests before any file writes occur. Update the watcher setup
around fs.watch, Stream.runHead, and Effect.forkChild so the test waits until
NFS.watch has registered and the stream is actively pulling, then proceed with
the existing write operations.

---

Nitpick comments:
In `@packages/platform-node-shared/test/NodeFileSystem.test.ts`:
- Around line 19-22: Add a test alongside the existing fs.watch coverage that
calls fs.watch(root) without options and verifies changes in nested paths are
not reported, preserving the expected non-recursive default behavior.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 520eecd6-6929-43b9-9f6f-3daa20f93917

📥 Commits

Reviewing files that changed from the base of the PR and between fa8d505 and 977d23e.

📒 Files selected for processing (2)
  • packages/effect/src/FileSystem.ts
  • packages/platform-node-shared/test/NodeFileSystem.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/effect/src/FileSystem.ts

Comment thread packages/platform-node-shared/test/NodeFileSystem.test.ts Outdated
@github-project-automation github-project-automation Bot moved this from Discussion Ongoing to Waiting on Author in PR Backlog Jul 28, 2026

Copy link
Copy Markdown
Contributor Author

Addressed the latest review in 5724b7c: the watch tests now establish a real readiness handshake by repeatedly touching a sentinel until the stream observes it, and the sentinel is filtered from assertions. I also added explicit coverage for fs.watch(root) with omitted options defaulting to non-recursive behavior.

@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

🤖 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 `@packages/platform-node-shared/test/NodeFileSystem.test.ts`:
- Around line 18-35: Update the watcher setup around the `fiber`,
`Deferred.await(ready)`, and `signalFiber` lifecycle so watcher errors or normal
closure before observing `readyName` cause the readiness wait to fail or exit
instead of hanging. Link the readiness wait to `fiber` completion, and ensure
`signalFiber` is interrupted whether readiness succeeds or the watcher
terminates unexpectedly.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 7e690f2e-2ca5-4a57-8dcc-462b66a6e98a

📥 Commits

Reviewing files that changed from the base of the PR and between 977d23e and 5724b7c.

📒 Files selected for processing (1)
  • packages/platform-node-shared/test/NodeFileSystem.test.ts

Comment thread packages/platform-node-shared/test/NodeFileSystem.test.ts Outdated

Copy link
Copy Markdown
Contributor Author

Addressed the watcher-lifecycle review in d67acc0. The readiness wait now races the watcher fiber’s completion, so startup errors or early closure surface immediately, and an ensuring finalizer always interrupts the sentinel writer.

@tim-smart
tim-smart enabled auto-merge (squash) July 29, 2026 03:47
auto-merge was automatically disabled July 29, 2026 04:42

Head branch was pushed to by a user without write access

@tylergibbs1

Copy link
Copy Markdown
Contributor Author

Fixed the Node CI timeout in a15fc71. The readiness signal used the test clock, so after its first pre-watcher write it never retried; it now delays on the live clock before writing, giving the watcher fiber time to acquire. Verified the focused NodeFileSystem suite 10 consecutive times on Linux/Node 26 (18/18 each), plus oxlint, dprint, and the package TypeScript build.

@github-actions

Copy link
Copy Markdown
Contributor

Bundle Size Analysis

File Name Current Size Previous Size Difference
basic.ts 6.63 KB 6.63 KB 0.00 KB (0.00%)
batching.ts 9.42 KB 9.42 KB 0.00 KB (0.00%)
brand.ts 6.31 KB 6.31 KB 0.00 KB (0.00%)
cache.ts 10.12 KB 10.12 KB 0.00 KB (0.00%)
config.ts 19.90 KB 19.90 KB 0.00 KB (0.00%)
differ.ts 20.03 KB 20.03 KB 0.00 KB (0.00%)
http-client.ts 20.94 KB 20.94 KB 0.00 KB (0.00%)
logger.ts 10.28 KB 10.28 KB 0.00 KB (0.00%)
metric.ts 8.55 KB 8.55 KB 0.00 KB (0.00%)
optic.ts 7.46 KB 7.46 KB 0.00 KB (0.00%)
pubsub.ts 14.26 KB 14.26 KB 0.00 KB (0.00%)
queue.ts 11.09 KB 11.09 KB 0.00 KB (0.00%)
schedule.ts 10.27 KB 10.27 KB 0.00 KB (0.00%)
schema-class.ts 18.86 KB 18.86 KB 0.00 KB (0.00%)
schema-fromJsonSchemaDocument.ts 28.78 KB 28.78 KB 0.00 KB (0.00%)
schema-representation-roundtrip.ts 25.09 KB 25.09 KB 0.00 KB (0.00%)
schema-string-transformation.ts 12.95 KB 12.95 KB 0.00 KB (0.00%)
schema-string.ts 10.65 KB 10.65 KB 0.00 KB (0.00%)
schema-template-literal.ts 14.85 KB 14.85 KB 0.00 KB (0.00%)
schema-toArbitraryLazy.ts 21.66 KB 21.66 KB 0.00 KB (0.00%)
schema-toCodeDocument.ts 24.10 KB 24.10 KB 0.00 KB (0.00%)
schema-toCodecJson.ts 19.00 KB 19.00 KB 0.00 KB (0.00%)
schema-toEquivalence.ts 18.73 KB 18.73 KB 0.00 KB (0.00%)
schema-toFormatter.ts 18.59 KB 18.59 KB 0.00 KB (0.00%)
schema-toJsonSchemaDocument.ts 22.23 KB 22.23 KB 0.00 KB (0.00%)
schema-toRepresentation.ts 19.27 KB 19.27 KB 0.00 KB (0.00%)
schema.ts 18.12 KB 18.12 KB 0.00 KB (0.00%)
stm.ts 12.05 KB 12.05 KB 0.00 KB (0.00%)
stream.ts 9.37 KB 9.37 KB 0.00 KB (0.00%)

@tim-smart
tim-smart merged commit 7bde6cc into Effect-TS:main Jul 29, 2026
15 checks passed
@github-project-automation github-project-automation Bot moved this from Waiting on Author to Done in PR Backlog Jul 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

4.0 bug Something isn't working

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

FileSystem.watch: recursive control removed, Node/Bun watches forced recursive

2 participants