You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
flows check never talks to the daemon, so it structurally cannot catch spec/daemon skew #502
flows check is a pure compile-and-preflight: it never talks to relayflowd. That is what makes it fast and worth having, and it also means the one validation tool we ship structurally cannot catch spec/daemon skew. Any field the npm packages gain before the runtime binary does behaves this way.
Reported in the Relayflows v2 Field Report (2026-09-18, Julian Fann), building a GitLab-sourced factory flow on CLI 2.0.19. Three of their four blockers were invisible to flows check, tsc --strict and 57 unit tests; only a live run surfaced them.
Evidence
#489 is the concrete instance: @relayflows/surface 2.0.19 and @relayflows/sdk 2.0.19 both declare cwd on an agent step, @relayflows/runtime-darwin-arm64 2.0.19 does not. tsc --strict accepted it, flows check returned exit 0, and the run then died:
FAILED [protocol_error] relayflowd could not complete the run request:
invalid_spec: unknown field "cwd" at steps[0] — refusing to guess (fail closed)
This issue is the class, not that instance: today a green check tells an author nothing about whether the daemon will accept the spec, which is the difference between a tool you trust and a tool you re-verify by running.
What to change
Give check a way to reach the daemon's validator. Either is acceptable:
Round-trip validation.flows check --against-daemon (or on by default when a daemon socket is reachable) submits the compiled spec to relayflowd for validation only — no run created, no journal written — and reports the daemon's refusal in the same diagnostic shape as a local one.
Version-lockstep packaging. Publish the runtime binary in lockstep with the npm packages so the three cannot disagree at the same version number. This closes the instance but not the class, so prefer it in addition to the round-trip, not instead of.
Acceptance
A spec containing a field the installed daemon rejects is refused by flows check, naming the same field and step the daemon names.
flows check with no daemon reachable keeps working exactly as today and says which mode it ran in, so a green check is never ambiguous about what it proved.
A test pins the skew case: a spec valid to the packages and invalid to the daemon must fail check.
Triage 2026-10-05: VALID — flows check is still daemon-free on main (packages/sdk/src/cli.ts:294-307), the kernel has no validate-only verb, and #517 explicitly left the daemon round-trip to this issue. The cited instance #489 is closed, so the regression test needs a synthetic field that the SDK accepts and the daemon rejects. #505 handles the matching check at the run-time hello handshake; keep the two separate.
Activity
flows check knows which specs will park or fail at run time, and says…
AgentRelayBot commentedon Oct 5, 2026
Triage 2026-10-05: VALID —
flows checkis still daemon-free on main (packages/sdk/src/cli.ts:294-307), the kernel has no validate-only verb, and #517 explicitly left the daemon round-trip to this issue. The cited instance #489 is closed, so the regression test needs a synthetic field that the SDK accepts and the daemon rejects. #505 handles the matching check at the run-timehellohandshake; keep the two separate.