Skip to content

fix(expr): normalize a bare scope key before jq so shorthand+jq hybrids resolve#6

Merged
graycyrus merged 1 commit into
mainfrom
fix/normalize-bare-scope-jq
Jul 8, 2026
Merged

fix(expr): normalize a bare scope key before jq so shorthand+jq hybrids resolve#6
graycyrus merged 1 commit into
mainfrom
fix/normalize-bare-scope-jq

Conversation

@graycyrus

@graycyrus graycyrus commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator

Bug: a condition/expression that mixes the simple-path shorthand with a jq pipe silently yields null

expr::run_jq compiled a hybrid like item.labels | any(.name == "in progress") | not — the simple-path shorthand's bare scope key (item, no leading dot) piped into real jq — as a jq program where bare item parses as an undefined jq function, failing to compile and yielding Null. A condition node then routes every item to false → 0 output.

Fix

normalize_bare_scope_ref(program, scope) (called at the top of run_jq): if the program starts with a bare identifier that is a top-level key of the scope (item/items/run/nodes) and the next char is . | [ or EOF (explicitly not (, so jq builtins like any(...)/map(...) are untouched), prepend . so it resolves as jq field access. Otherwise unchanged (Cow::Borrowed, no alloc). Leading-dot programs never match; plain dotted paths never reach run_jq. Only currently-null-returning expressions change behavior.

Tests

5 expr tests (normalize / no-double-dot / builtins-untouched / pipe-only / not-in-scope) + a condition-node jq test. Full suite green (310 lib + doctests).

Summary by CodeRabbit

  • Bug Fixes
    • Improved handling of condition expressions that reference scoped values, so jq-style expressions now evaluate correctly instead of being treated as invalid.
    • Fixed routing for fields containing jq expressions, ensuring conditions resolve truthfully for matching and non-matching values.
    • Preserved existing behavior for already-correct expressions and unsupported identifiers.

A workflow builder can emit a hybrid condition field like
`item.labels | any(.name == "in progress") | not` — the simple-path
shorthand's bare scope key (no leading dot) piped into a real jq
program. That string fails is_simple_dotted_path (it contains a `|`)
so it falls to run_jq, where a bare `item` at the head parses as an
undefined jq function, the compile fails, and the expression silently
resolves to Null — which a condition node's truthiness check then
routes to `false` for every item.

normalize_bare_scope_ref() rewrites a program that starts with a bare
identifier which is a top-level key of the expression scope
(item/items/run/nodes) into a leading-dot jq field access, as long as
the identifier isn't being called as a jq function (next char is not
`(`). Leading-dot programs and unrecognized identifiers pass through
unchanged.
@graycyrus
graycyrus merged commit 68590ed into main Jul 8, 2026
0 of 2 checks passed
@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4da65b8d-2ff8-4a92-be4b-2975e59b7ab4

📥 Commits

Reviewing files that changed from the base of the PR and between 56d81df and e643cf6.

📒 Files selected for processing (2)
  • src/expr.rs
  • src/nodes/control_flow/condition.rs

📝 Walkthrough

Walkthrough

Adds a jq expression normalization step in src/expr.rs that detects bare scope key identifiers at the start of jq programs and prepends a dot so jq treats them as field references. run_jq now applies this normalization. Corresponding tests are added in expr.rs and condition.rs.

Changes

Bare Scope Key Normalization

Layer / File(s) Summary
Normalization helper and run_jq wiring
src/expr.rs
Adds Cow import and normalize_bare_scope_ref, which prepends . to jq programs starting with a bare scope key followed by field-access boundary characters; run_jq normalizes programs before compiling.
Normalization tests and condition integration
src/expr.rs, src/nodes/control_flow/condition.rs
Unit tests verify normalization for hybrid shorthand/pipe expressions, leading-dot preservation, builtin/function-call protection, and non-scope-key identifiers; a new tokio test in condition.rs verifies routing based on jq predicate truthiness, alongside a reformatted assertion.

Estimated code review effort: 2 (Simple) | ~12 minutes

Possibly related PRs

  • tinyhumansai/tinyflows#5: Extends the same ConditionNode field resolution and truthiness routing logic that this PR's jq normalization and tests build upon.

Poem

A dot before the key, so small, so neat,
Turns "item" from a stranger to something petite.
No more undefined calls to make jq frown,
Just fields resolving smoothly up and down. 🐰
Hop, test, and pipe — the labels all check out!

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Comment @coderabbitai help to get the list of available commands.

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.

1 participant