I'll be damned. What a newb problem. Though it was a little tricky so I'll lay this out for others.
Here's the spool dir:
# ls -ltotal 32lrwxrwxrwx 1 cyrus mail 10 Oct 10 2017 defaultbc -> filters.bc-rw------- 1 cyrus mail 5080 Aug 31 2021 filters.bc-rw------- 1 cyrus mail 4878 Aug 9 2021 filters.script-rw------- 1 cyrus mail 5568 Jan 13 20:24 filters.script.bc-rw------- 1 cyrus mail 5431 Jan 13 20:24 filters.script.script# file *defaultbc: symbolic link to filters.bcfilters.bc: Cyrus sieve bytecode data, version 27, network-endianfilters.script: ASCII text, with CRLF line terminatorsfilters.script.bc: Cyrus sieve bytecode data, version 27, network-endianfilters.script.script: ASCII text, with CRLF line terminators
And the file I'm uploading:
$ ls -l filters.script-rw-r--r-- 1 phil users 5159 Jan 13 20:24 filters.script
It turns out I was uploading `filters.script`, but I was activating `filters`.
Nice catch, and thanks!
All that said, I'm still wondering about my bigger question - is there no way to enable a "trace" mode for Cyrus Sieve? I found `sieve-test` over in the Dovecot project, which is quite useful for debugging a script, but wouldn't have helped so much in a case like this. If I could get the sieve server to output tracing messages as it processed a message, it would be obvious the rules it was running weren't the ones I expected it to.