Skip to content

test(agent): the four conversation red paths, and an example that shows why - #597

Open
HappyDevs1 wants to merge 2 commits into
mainfrom
test/conversation-red-paths-and-example
Open

HappyDevs1 wants to merge 2 commits into
mainfrom
test/conversation-red-paths-and-example

Conversation

@HappyDevs1

@HappyDevs1 HappyDevs1 commented Sep 15, 2026

Copy link
Copy Markdown
Collaborator

Part 2 of 3 closing out #375. Stacks conceptually on #596 but is independent — this touches no schema.

Why

#375 asks for red-path tests covering a changed later user turn, a missing turn, an extra turn, and a tool-call divergence after turn one, plus a runnable example. What existed was adjacent but weaker: conversation_windows_require_every_delivery_and_every_call is a unit test over validate_delivery_windows (it checks the validator, not a replay), plus an early-exit test. Nothing edited a flow file against a fixed recording — which is what an actual regression looks like.

The four red paths

Each edits the spec against a fixed cassette and asserts where the run failed:

Drift Reported as
delivery 1's user: edited turn 2: message 2 (user) content changed
a delivery removed the agent made 1 model calls, the recording has 2
a delivery added turn 3: the system under test made 3 model calls, the recording has 2
tool set changed on delivery 1 turn 2: tools offered changed

Asserting the location is the point — is_err() alone would pass just as happily if every drift were reported at delivery 1. The changed-turn case must get past delivery 0 cleanly and fail at turn 2.

Falsifiability checked, not assumed: I removed the drift from the changed-turn test and confirmed it then fails (replay succeeds, expect_err panics) — so it detects that specific edit rather than failing for an incidental reason.

The example

examples/agent-demo/cancel-order.flow.yaml + cancellation_agent.py — a real multi-turn OpenAI-SDK agent (delivery 0 via FLOWPROOF_PROMPT, later deliveries as JSON lines on stdin, history kept across turns). It's the canonical confirmation-gate case, and the only shipped flow using conversation:.

Its assert_no_tool_call is delivery-local on purpose: across the whole conversation the agent does call cancel_order, so a flow-wide guard would certify nothing. the_conversation_example_keeps_its_delivery_local_guard pins that shape.

No cassette is committed — recording one needs a real model, and hand-writing a trace would mint exactly the unearned recording this tool exists to prevent. Same posture as weather.flow.yaml.

Test plan

  • cargo test -p flowproof-cli --lib — 126 pass, including 11 conversation tests.
  • cargo test -p flowproof-cli --test examples_resolve — 9 pass.
  • cargo fmt --check, cargo clippy -p flowproof-cli --all-targets -- -D warnings clean.
  • ⚠️ Pre-existing, unrelated: doctor_ai_e2e fails on this machine only because it has a real API key stored (api key: configured), while the test asserts the no-key path. Untouched by this PR; expected green in CI.

Copilot AI lite review requested due to automatic review settings September 15, 2026 13:28

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

…ws why

#375 asked for red-path tests covering a changed later user turn, a
missing turn, an extra turn, and a tool-call divergence after turn one.
What existed was adjacent but weaker: a unit test over
validate_delivery_windows, which checks the validator rather than a
replay, and an early-exit test. None of them edit a flow file against a
fixed recording, which is what a real regression looks like.

These four do, and each asserts WHERE the run failed, not just that it
did. That distinction is the whole value: a test asserting is_err() would
pass just as happily if every drift were reported at delivery 1. A
changed turn 2 must fail at turn 2, having replayed turn 1 cleanly first.

The example is the other gap. cancel-order.flow.yaml is the canonical
case the feature exists for - the agent must ask before it cancels, and
cancel only once confirmed - and it is the only shipped flow using
`conversation:`, so the grammar now has a user. Its guard is
delivery-local on purpose: across the whole conversation the agent DOES
cancel, so a flow-wide guard would certify nothing. The test pins that
shape, because an example that quietly stops demonstrating its point is
worse than no example.

No cassette is committed: recording one needs a real model, and
hand-writing a trace would mint exactly the kind of unearned recording
this tool exists to prevent. Same posture as weather.flow.yaml.
@HappyDevs1
HappyDevs1 force-pushed the test/conversation-red-paths-and-example branch from d78ed1e to 7023e13 Compare September 15, 2026 13:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants