Skip to content

refactor(session): one watch plan, registered by every host - #417

Merged
codecaaron merged 5 commits into
mainfrom
wc/session-watch
Oct 12, 2026
Merged

codecaaron merged 5 commits into
mainfrom
wc/session-watch

Conversation

@codecaaron

@codecaaron codecaaron commented Oct 12, 2026 •

Copy link
Copy Markdown
Owner

Gut check C ("one watch plan") and B4. Opened as a single PR for Linux CI, since it changes what each host registers with its watcher. spike-codex is reviewing the same range locally.

What changed

  • Red first 053d228 (B4): the Turbopack and CLI orchestrator watches an absent system path outside the root, and creating it reloads the system. Red on main 0e9ceda: no watcher is opened for it.

  • One watch plan 485ff93: ExtractionSession.watchPlan(covered) returns one plan.

    • files: the system module and the modules it read, asset sources, configuration inputs.
    • missing: the paths the system load found absent, less any inside the host's covered recursive roots.
    • directories: the canonical external roots.

    Hosts keep only registration:

    • Vite: chokidar add, each path once. The root and the external directories count as covered, so no absent file is watched inside a watched directory (the inotify finding).
    • Next webpack: webpack's file, missing and context dependencies.
    • unplugin: Rollup's addWatchFile over its analysed files plus the plan's files and absent paths, with no directories, since Rollup's graph covers imported kit sources.
    • Turbopack/CLI orchestrator: dependency watchers.

Host-visible differences

  • Config inputs (package.json, the tsconfig chain) are now watched by Vite, Next webpack and unplugin (unplugin used to watch only the root tsconfig.json).
  • Vite also registers asset sources.
  • The orchestrator watches absent system paths outside the root.

Stated limit

The coalescing scheduler stays per host. The mechanism is already one CoalescingWindow. Moving the windows into the Session adds about as much as it deletes and shifts Linux timing, and Vite's system reload needs per-window outcome scoping.

Proof

  • Red-first row above.
  • 707 targeted tests (Session, Vite, unplugin, Next, CLI).
  • All 13 local macOS tiers green on 485ff93.

Review fix (spike-codex's P1, silent stale CSS)

  • The P1: a plugin instance reused with a replacement dev server kept its registration memo, so outside-root paths were never registered with the new server's watcher.
  • Fix: b178dcb keys the memo by watcher.
  • Witnesses, both red on 485ff93 and green on b4cabf8:
    • 16365c6: a registration row, where a replacement watcher gets every path again;
    • b4cabf8: a real Vite witness. One plugin object, server 1 closed, server 2 started, and an outside-root palette edit must reach server 2's CSS.

Further stated limits (from the review)

  • Absent config inputs: they sit in the plan's files, so the covered-root filter (which applies only to missing) doesn't screen them. Vite therefore adds an absent in-root tsconfig.json to its watcher. No CSS failure was shown.
  • Config edits under Vite: registration doesn't route them. Vite's hot-update path ignores .json and checks only system dependencies, so a package.json edit doesn't reach the Session. This routing predates this PR.

🤖 Generated with Claude Code

codecaaron and others added 5 commits October 11, 2026 21:29
…ide the root

Gut-check item B4. The orchestrator watched the system's dependencies,
asset sources and configuration inputs outside the root, but not the
paths the system load found absent, so creating one did not reload the
system until another edit or a restart. Red on 0e9ceda.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Gut check C ("one watch plan") and B4. Four hosts decided what to watch
in four places and disagreed: Vite left out asset sources and config
inputs, Next webpack config inputs, unplugin config inputs beyond the
root tsconfig, and the Turbopack and CLI orchestrator the paths the
system load found absent. The Session's watchPlan(covered) now returns
one plan: the files whose change it acts on (the system module and the
modules it read, asset sources, configuration inputs), the absent paths
whose creation reloads the system (less those a host's recursive watch
covers), and the canonical external roots. Hosts keep only registration:
Vite's watcher, webpack's dependency kinds, Rollup's addWatchFile (with
its analysed files, as Rollup watches only its graph), and the
orchestrator's dependency watchers.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
… again

spike-codex's #417 P1: one plugin instance reused with a replacement dev
server kept its registration memo, so outside-root paths (an external
palette module) were never added to the new server's watcher and their
edits left stale CSS. Red on 485ff93.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
…ontext

spike-codex's #417 P1 (silent stale CSS). The registration memo lived as
long as the plugin context, so a reused plugin instance whose dev server
was replaced skipped every path it had given the old watcher, and the new
server never watched an outside-root system module. The memo is now
keyed by watcher.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
…t edit

spike-codex's retained witness for the #417 P1, on a real Vite server: one
plugin object, a first server closed, a second server started; editing a
system module outside the root (a palette the theme imports) must reach the
second server's served CSS. Red against 485ff93's context (the edit never
arrives); green with b178dcb.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
@codecaaron
codecaaron merged commit c64fe6b into main Oct 12, 2026
14 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.

1 participant