con-duct ls --eval-filter: silent/misleading on malformed expressions
- Dominant language
- Python
- Stars
- 12
- Forks
- 6
- Avg merge
- 11d 11h
- Merged PRs (30d)
- 1
Description
## Summary
Two related UX gaps in `--eval-filter`. Both classify as "filter expression is malformed" and should behave the same way: emit a clear single-line warning and return no rows.
1. **Type-mismatch is silent.** The filter namespace receives `exit_code` as `int`, so `exit_code == '0'` compares int to str and never matches. The column displays `"0"` and `-f json` emits `"0"` as a string, so the failing pattern looks right. The result is zero rows, no warning, no hint.
2. **NameError is misattributed.** An undefined identifier in the expression raises `NameError` during eval, but the current handler blames the file: `Failed to load file <_io.TextIOWrapper name='.duct/logs/..._info.json' mode='r' encoding='utf-8'>: name 'foo' is not defined`. The JSON load succeeded; the filter eval is at fault. The message also leaks the Python `_io.TextIOWrapper` repr and repeats once per file.
## Reproducer — type mismatch (silent)
```sh
cd "$(mktemp -d)"
duct -- echo one >/dev/null
duct --fail-time 0 -- bash -c 'exit 1'
con-duct ls # 2 rows, EXIT_CODE shows "0" / "1"
con-duct ls --eval-filter "exit_code == '0'" # 0 rows (silent)
con-duct ls --eval-filter "exit_code == 0" # 1 row
```
## Reproducer — NameError misattribution
```sh
cd "$(mktemp -d)"
duct -- true
con-duct ls --eval-filter "foo == 'bar'"
# [WARNING] con_duct.ls: Failed to load file <_io.TextIOWrapper ...>: name 'foo' is not defined
```
## Proposed behavior
One warning per invocation (not per file), blaming the expression:
- Type-mismatch:
```
[WARNING] --eval-filter: 'exit_code' is int, compared to str — expression will never match
```
- NameError:
```
[WARNING] --eval-filter: name 'foo' is not defined
```
Implementation-shape: split the try/except in `ls.py` that today wraps both the JSON load and the filter eval. JSON errors stay file-scoped; eval errors are expression-scoped and emit once.
Low-risk prerequisite: the filter expression can be pre-analyzed once per invocation (not once per file) to detect literal-type mismatches against the known field types (`exit_code: int`, `message: str`, etc.).
## Scope
Reproduces on v0.19.0 and current `main`. Longstanding, not a regression. Surfaced during pre-0.20.0 QE.
Contributor guide
Assessment
This issue has not been assessed yet.