Stateful Voice-Flow Shift-Left Framework

Status: Implemented first slice · Date: 2026-07-09 · Reference: Property management, +1 510-216-0079

Decision

RIFF validates multi-call, multi-object workflows with declarative stateful scenarios before OTA. Scenarios run production tool functions and deterministic choice resolution against a stateful backend implementing the production client interface.

This bridge catches missing objects, incorrect spoken lists, ambiguous selection, cross-object mutation, and weak audit evidence locally. Telephony and external integration remain OTA concerns.

Contract and Artifacts

riff_stateful_scenario_v1 files declare an adapter, synthetic identity, ordered actions, captured references, and exact/contains/excludes assertions. The generic runner writes:

Fixtures use synthetic data only and never contain credentials, real caller identity, raw card data, or raw passwords.

Property-Management Proof

  1. Create separate sink and heater requests.
  2. List both and verify both are spoken.
  3. Select, read, and update the first request.
  4. List again, then select, read, and update the second request.
  5. Read both and prove updates did not cross ticket boundaries.
  6. List both at the end and retain ordered audit evidence.

The adapter calls the production create, list, get, and update tools. Selection uses the compiled flow's locked-choice contract and production resolver.

Shift-Left Gate

The CI test discovers every YAML file in tests/scenarios, so adding a scenario automatically adds a gate.

.venv/bin/python scripts/run-stateful-scenario.py \
  tests/scenarios/property_management_two_tickets.yaml \
  --out runs/stateful-scenarios/property_management_two_tickets

This command is local and places no phone call. A real OTA call still requires explicit human GO.

Extension Rules

  1. Implement the production client surface in a stateful simulator.
  2. Map scenario actions to production tools and resolvers in a small adapter.
  3. Add a synthetic scenario with observable assertions.
  4. Log object, call, and operation IDs in ordered events.
  5. Block promotion on scenario failure before OTA.

Business behavior stays out of the generic runner. Production limitations are fixed in production code, and the revealing scenario remains as the regression gate.