Docs: workflow filter/if examples use single-quoted strings, which evalexpr rejects — workflow silently never fires
- Dominant language
- Rust
- Stars
- 32.7k
- Forks
- 4.3k
- Avg merge
- 1d 13h
- Merged PRs (30d)
- 253
Description
**Describe the bug**
`ARCHITECTURE.md` documents workflow trigger filters and step conditions using **single-quoted** string literals:
```yaml
# ARCHITECTURE.md:518
filter: "str_contains(trigger_text, 'P1')"
# ARCHITECTURE.md:524
if: "str_contains(trigger_text, 'production')"
```
`evalexpr` (11.3.1) does not treat `'P1'` as a string literal — it parses it as a *variable identifier*, which is unbound, so condition evaluation errors and the workflow is skipped. Copying the documented example verbatim produces a workflow that is created successfully, appears healthy, and then **never fires**.
The failure is silent from the user's side: no run row is created, no error surfaces in the client, and the only evidence is a `WARN` in the relay log. It reads exactly like "my trigger just didn't match."
The crate's own unit tests use the **double-quoted** form throughout (e.g. `crates/buzz-workflow/src/lib.rs`: `evaluate_condition("str_contains(trigger_text, \"P1\")", ...)`), so the test suite passes while the documented form is broken — which is presumably why this hasn't surfaced.
**Steps to reproduce**
1. On a self-hosted relay, create a workflow using the documented single-quoted form:
```yaml
name: "Repro"
trigger:
on: message_posted
filter: "str_contains(trigger_text, 'RECEIPT')"
steps:
- id: announce
action: send_message
text: "fired"
```
2. Post a message containing `RECEIPT` in that channel.
3. Nothing happens. No row appears in `workflow_runs`. The client shows no error.
4. Relay log contains:
```
WARN Trigger filter error: condition evaluation error:
'str_contains(trigger_text, 'RECEIPT')': Variable identifier is not bound to
anything by context: "'RECEIPT'". — skipping workflow
```
5. Change the filter to double-quoted strings inside a single-quoted YAML scalar and repeat:
```yaml
filter: 'str_contains(trigger_text, "RECEIPT")'
```
6. The run is created and completes; the `send_message` step posts to the channel.
**Expected behavior**
Either the documented examples work as written, or the docs show the form that actually works. Two suggestions, not mutually exclusive:
1. **Fix the docs** (smallest change): update the `filter:` and `if:` examples in `ARCHITECTURE.md` to `'str_contains(trigger_text, "P1")'`, and consider a one-line note that condition strings are `evalexpr` expressions in which string literals must be double-quoted.
2. **Surface the failure**: a filter that errors is a user-authored bug that currently only appears in relay logs. Recording a `failed` run (or storing the condition error on the workflow) would turn a silent no-op into something debuggable from the client.
**Version and platform**
- Buzz version: relay built from source at commit `dd222a5` (2026-07-26); desktop 0.4.26
- OS: macOS 15 (Apple Silicon); self-hosted relay with Postgres 17 / Redis 7 / MinIO
**Logs / additional context**
Found while running a self-hosted evaluation of Buzz with an externally-harnessed `buzz-acp` agent. Happy to open a PR against the two `ARCHITECTURE.md` lines if that's useful.
Investigated and drafted jointly by @mjsherbs-byte and Claude (Anthropic) — the repro came out of an agent-run evaluation session.
Contributor guide
Research direction
Update the filter and if examples at ARCHITECTURE.md:518 and :524, using the working quoting shown in crates/buzz-workflow/src/lib.rs. Read those examples and the crate tests first, then verify the documented YAML uses double-quoted evalexpr string literals and explains the requirement; the documentation fix is done when the copied examples match the tested form.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- documentation
- Issue type
- Documentation
- Difficulty
- 1/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 82/100