Skip to content

flows: flows check --watch — save-time terminal feedback loop #319

Description

@kjgbot

flows: flows check --watch — save-time terminal feedback loop

Context

Today, an author writing a flow discovers authoring errors only by running flows check explicitly after each save. That's a save → alt-tab → flows check <path> → read output → alt-tab back loop, easily 8-10 seconds per iteration. For an author actively iterating on a spec, that friction is exactly what turns v1's "wrote a flow, hit step 26, fixed, tried again, hit another problem, fixed, ..." pain into v2's version of itself — a check pipeline that catches the problem is only useful if the author invokes it.

This slice adds a --watch flag on the existing flows check CLI so the author leaves it running in a split terminal and every save re-checks in <1s.

Non-goals (deliberately deferred to sibling slices):

  • LSP / editor extension (slice L4)
  • TypeScript language service plugin for cross-file checks (slice L2)
  • JSON Schema for YAML editor validation (slice L1)
  • TUI or interactive controls — this is plain text output, cleared and re-rendered per change

--watch is the cheapest deliverable in the "author sees errors while writing" bucket. It requires no editor plumbing and no per-IDE extension.

Scope

Add a --watch flag on flows check (packages/sdk/src/cli/check.ts). When set:

  1. Compile the target flow file once. Print the same report the existing flows check prints (accepted + all diagnostics), preceded by an ANSI clear-screen so a re-render replaces the prior report.
  2. Watch a set of files for changes:
    • The flow file itself.
    • Every relative use: import reachable from the flow file (walk the loader graph once at startup and after every re-check, since the set can grow).
    • The nearest flows.json found by walking parent directories from the flow file (SURFACE.md §5 project-config discovery).
    • The kernel/agent/CLI adapter binaries are NOT watched — a change to those isn't an authoring change, and probing them re-runs preflight anyway.
  3. Debounce changes at ~150 ms. Multiple saves within the debounce window collapse into one re-check.
  4. On each re-check, clear the screen and print the fresh report.
  5. --json remains supported alongside --watch. In JSON mode, one report object is printed per re-check on its own line; no screen clear (so flows check --watch --json <path> | jq streams).
  6. Exit cleanly on Ctrl-C (SIGINT). Exit code is 0 if the last run was accepted, 1 otherwise, 2 if the initial file was missing / unreadable.

Refusals (unchanged)

Every refusal flows check already produces (unknown headers, invalid verification, unresolved refs, cycles, model_unknown, cli_missing, etc.) is preserved verbatim. --watch is a runner around the same pipeline, not a re-implementation.

Acceptance evidence

  • flows check --watch testdata/hello-deterministic.flow.yaml prints an accepted report; editing the file adds - run: broken syntax — within ~1 s a fresh report appears with the diagnostic, screen cleared.
  • A flow that imports ./reviewer.flow.ts via use: — editing reviewer.flow.ts retriggers the watch loop for the parent flow.
  • Touching the nearest flows.json (adding an unlisted model to the allowlist, then removing it) retriggers.
  • Rapid save loop (20 saves in 500 ms via for i in $(seq 20); do touch f; done) produces at most 2 re-checks (one head, one tail after debounce).
  • flows check --watch --json flow.yaml streams valid JSON, one object per re-check, no ANSI codes.
  • Ctrl-C exits with the correct code for the last successful state.

Files to touch

  • packages/sdk/src/cli/check.ts — add --watch flag parsing, wire to watcher.
  • packages/sdk/src/cli-watch.ts — new. File-set watcher, debounce, re-check loop. Prefer chokidar (already common in the SDK toolchain) or fs.watch if lighter-weight is preferred; the check pipeline dominates the cost so watcher-lib choice is secondary.
  • packages/sdk/tests/cli-watch.test.ts — new. Fixture-based; a Node test harness spawns flows check --watch, writes to the fixture, and asserts the re-checked output over the debounce window.
  • docs/SURFACE.md §5 — add one paragraph on --watch under flows check. No spec-shape change; the flag is a runner.

Out of scope

  • LSP protocol / editor integration.
  • Watching .ts files that aren't use:-reachable but might be imported by them transitively — those are the tsserver plugin's job (slice L2).
  • YAML schema-based validation (slice L1).
  • Colored diff of report-vs-prior-report — this is nice-to-have; the existing report format is already terse enough that a full re-render is not visually noisy.

Depends on

Nothing new. flows check already ships.

Follow-ups

  • Slice L2 (@relayflows/ts-plugin) — same check pipeline surfaced in TS editors.
  • Slice L1 (YAML JSON Schema) — same check pipeline surfaced in YAML editors.
  • Slice L4 (full LSP) — only if L1 + L2 + this prove insufficient.

Activity

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions