Skip to content

wavekat/wavekat-flow

Repository files navigation

WaveKat Flow

npm Crates.io docs.rs

Single source of truth for the WaveKat call-flow ("Receptionist") document format.

A flow is the declarative IVR document that powers WaveKat voice lines — a greeting, an hours check, a menu, voicemail, a transfer — authored as YAML, validated against one schema, and executed by the daemon. Two codebases need to read and write it:

Consumer Language What it does with a flow
The WaveKat platform TypeScript authors, edits, validates, freezes on publish
The voice daemon Rust parses, validates, runs the flow on a live call

Historically each maintained a hand-ported twin of the model and validator, kept in sync by convention (schema_version negotiation + "check the other side" comments) with no shared test corpus. This repo removes that drift risk by making the format's definition live in exactly one place.

What lives here

schema/flow.v1.schema.json     # THE source of truth — the normative document shape
conformance/v1/                # the cross-language contract: docs + expected outcomes
packages/flow-schema/          # @wavekat/flow-schema  (npm)   — generated types + authoring logic
crates/wavekat-flow/           # wavekat-flow          (crate) — generated types + validator + engine
  • The schema is authoritative. Both the TypeScript package and the Rust crate generate their model types from schema/flow.v1.schema.json (json-schema-to-typescript and typify respectively). Neither hand-writes the model; CI fails on drift.
  • The corpus is the contract. Every document in conformance/ carries its expected outcome — structural and semantic — and both languages run it, so a document means the identical thing on both sides. This is also the backward-compatibility guarantee: a corpus case is frozen once added, so a schema change that would reject a previously-valid document fails CI. See conformance/README.md.
  • The logic lives here too. Beyond the generated model, each package carries its language's hand-written half of the format: @wavekat/flow-schema — safe-subset YAML parsing, semantic validation, hours math, comment-preserving source edits, and flow diffing (authoring side); wavekat-flow — semantic validation, hours math, and the flow interpreter with its run trace (execution side).

What a schema cannot own

A JSON Schema defines the document shape (types, enums, required fields, the kind discriminated union, defaults). It cannot express the format's semantic rules — graph reachability, exit-set exactness, hours/timezone math, DTMF digit validity, prompt length, safe-subset YAML parsing, comment-preserving edits, or the interpreter. Those live here as hand-written code per language — pinned by the shared corpus, not generated. See schema/README.md for the exact boundary.

Versioning

  • schema_version is a property of the document (currently 1). Each version gets its own schema/flow.vN.schema.json and its own frozen conformance/vN/ corpus. Growth is additive; an unsupported version is rejected, never silently migrated.
  • The npm package and the Rust crate version independently of schema_version (they track implementation releases). A given package release advertises which schema_versions it understands via SUPPORTED_SCHEMA_VERSIONS.
  • Both artifacts stay on 0.0.x while the format settles: every release may break API, and nothing is promised beyond "the corpus is green". They move past 0.0.x once the consumer repos have adopted the published packages.

Status

The consolidation was staged in three phases; the checkbox-level detail lives in docs/ROADMAP.md.

  • Phase 1 — foundation. Done. The normative schema, the conformance corpus + back-compat runner, and both packages generating their model types from the schema, corpus green in TS and Rust.
  • Phase 2 — full consolidation. Done. The hand-written logic moved in (TS: safe-subset parse, comment-preserving mutation, semantic validation, hours; Rust: validation, hours, engine, trace), each adapted to the generated types, with the corpus extended to pin the semantic outcomes in both languages.
  • Phase 3 — publish & adopt. In progress. The repo is public and both packages are published (releases are cut automatically by release-please from a single combined release PR). Remaining: switch the platform and the voice daemon from their in-repo copies to the published artifacts, and migrate the narrative format spec (doc 48) into docs/.

This extends the "Placement" section of doc 48 (the original call-flow design doc), which had planned only to publish the JSON Schema and extract the Rust engine crate — it had not planned the shared codegen + conformance corpus this repo adds.

Development

Requires Node 22 (pnpm) and a stable Rust toolchain.

# TypeScript package
pnpm install
pnpm --filter @wavekat/flow-schema gen        # regenerate model.ts from the schema
pnpm --filter @wavekat/flow-schema typecheck
pnpm --filter @wavekat/flow-schema test        # runs the conformance corpus

# Rust crate (types regenerate from the schema on every build)
cargo test -p wavekat-flow                      # runs the conformance corpus

After editing schema/flow.v1.schema.json, run pnpm --filter @wavekat/flow-schema gen and commit the regenerated files — CI rejects drift.

License

Licensed under Apache 2.0.

Copyright 2026 WaveKat.

About

Single source of truth for the WaveKat call-flow (Receptionist) document format: normative JSON Schema, cross-language conformance corpus, generated TS package + Rust crate.

Topics

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors