Skip to content

Add 'refresh' verb to playwright-server / vitest-server / logs-server to flush in-place without re-taking ownership from a running TUI #59

@DawidWraga

Description

@DawidWraga

Problem

When an agent (Claude Code, etc.) needs to invalidate cached state inside a running daemon — most commonly the playwright-server module cache after editing a non-spec .ts file (UI model, fixture helper) — the only tool available today is shutdown + re-serve. That works, but it has a nasty side effect when the user is running davstack start (the TUI):

  1. The TUI launches the daemons and adopts their PIDs.
  2. The agent runs playwright-server shutdown → the TUI's child dies.
  3. The agent runs playwright-server serve → a new daemon starts, owned by the agent's shell, not the TUI.
  4. The TUI's panel now shows "not running" until the user manually restarts it, and stdout/stderr is going to the agent's terminal instead of the TUI's log panel.

In other words: an agent doing routine cache-busting silently steals the daemon out of the user's TUI session. The user has to notice and re-claim.

Concrete cases

  • playwright-server: spec files get cache-busted via ?t=${Date.now()} (see session.ts:323), but any module a spec imports (*.ui.ts, fixtures/*.ts) is held in the worker's ESM cache forever. After editing a UI model, the daemon serves stale code until someone restarts.
  • vitest-server: similar story for non-test code edits the vitest daemon doesn't pick up.
  • logs-server: less impacted by code reload, but config edits or schema migrations to the per-session SQLite still need a clean way to flush without killing the process.

Proposal

Add a refresh verb to each of the three servers that does in-place reinitialisation without exiting:

playwright-server refresh        # flushes spec-module ESM cache; re-reads config; reseats warm context if storageStatePath changed
vitest-server refresh            # restarts the vitest worker pool / clears transform cache; re-reads config
logs-server refresh              # re-reads config (cors, ports), reopens DB handles, flushes per-session SQLite cache

HTTP shape (mirrors existing shutdown / refresh-auth):

POST /refresh
→ { ok: true, refreshedAt: <iso> }

CLI shape:

playwright-server refresh        # exits 0 on success
playwright-server refresh --hard # equivalent to today's shutdown + serve, for the rare case it's actually wanted

Implementation notes (playwright-server, by way of example)

  • The cache problem is mostly the Node ESM loader. Two viable strategies:
    1. Re-register the loader hook with a new revision so subsequent dynamic imports get a fresh URL — ?t=${Date.now()} applied to ALL imports under the spec, not just the spec itself. Simplest; doesn't free memory but kills the stale-module problem.
    2. Spawn a fresh worker to host the spec module evaluation and discard the old one. Cleaner; more moving parts.
  • Either way the warm Chromium context, persistent profile, and HTTP socket stay alive across the refresh. That's the whole value prop: the TUI's adopted PID never changes, the chromium window doesn't flash, and any in-flight goto/runFile requests either complete or get a clean 503.
  • check should learn a refreshedAt field so the TUI can surface "last refreshed 12s ago" in its status panel.

Why this matters

Agentic loops over playwright-server land somewhere around 10-30 edit-rerun cycles for a feature. Today every cache-stale rerun forces either a noisy diagnostic ("why is my test still failing?") or a shutdown+serve that breaks the user's TUI session. A refresh verb closes that gap without making the agent and the human fight over daemon ownership.

Related

  • packages/playwright-server/src/session.ts:323 — current spec-only cache bust
  • packages/playwright-server/src/spec-runner.ts — registration-intercept module loader
  • packages/playwright-server/src/http.ts — existing /refresh-auth + /shutdown endpoints
  • packages/vitest-server/src/http.ts — same shape
  • packages/logs-server/src/server.ts — server entry; would need a refresh hook into config + db-cache

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions