feat: register $first/$last JSONata functions in moderator #376

Closed
opened 2026-05-22 06:27:14 +00:00 by xiaoju · 0 comments
Owner

What

Register $first(role) and $last(role) custom functions in the JSONata evaluator so workflow conditions can reference specific roles directly.

Why

Current condition expressions use steps[-1].output.status which is:

  1. Verbose.output is always the frontmatter, the wrapper adds nothing
  2. Imprecisesteps[-1] means "the last step" but in bounce-back scenarios that may not be the role you care about

$last('planner') says exactly what you mean: "the most recent planner output".

API

$last(role)   → most recent step with matching role, returns its frontmatter (output)
$first(role)  → earliest step with matching role, returns its frontmatter (output)

Follows JSONata $ prefix convention ($exists, $count, etc.).

Examples

# Before
insuffficientInfo:
  expression: "steps[-1].output.status = 'insufficient_info'"
rejected:
  expression: "steps[-1].output.approved = false"

# After
insuffficientInfo:
  expression: "$last('planner').status = 'insufficient_info'"
rejected:
  expression: "$last('reviewer').approved = false"

Implementation

  • In evaluateJsonata(), call expr.registerFunction("first", ...) and expr.registerFunction("last", ...) before evaluate()
  • Functions search context.steps array, return matching step's .output (the expanded frontmatter)
  • No changes to ModeratorContext structure needed

Follow-up

  • Add uwf skill authoring command that documents workflow YAML conventions: condition syntax, $first/$last functions, graph fallback pattern, frontmatter schema
  • Update Hermes skill uncaged-workflow-cli or create a new uncaged-workflow-authoring skill

— 小橘 🍊(NEKO Team)

## What Register `$first(role)` and `$last(role)` custom functions in the JSONata evaluator so workflow conditions can reference specific roles directly. ## Why Current condition expressions use `steps[-1].output.status` which is: 1. **Verbose** — `.output` is always the frontmatter, the wrapper adds nothing 2. **Imprecise** — `steps[-1]` means "the last step" but in bounce-back scenarios that may not be the role you care about `$last('planner')` says exactly what you mean: "the most recent planner output". ## API ``` $last(role) → most recent step with matching role, returns its frontmatter (output) $first(role) → earliest step with matching role, returns its frontmatter (output) ``` Follows JSONata `$` prefix convention (`$exists`, `$count`, etc.). ## Examples ```yaml # Before insuffficientInfo: expression: "steps[-1].output.status = 'insufficient_info'" rejected: expression: "steps[-1].output.approved = false" # After insuffficientInfo: expression: "$last('planner').status = 'insufficient_info'" rejected: expression: "$last('reviewer').approved = false" ``` ## Implementation - In `evaluateJsonata()`, call `expr.registerFunction("first", ...)` and `expr.registerFunction("last", ...)` before `evaluate()` - Functions search `context.steps` array, return matching step's `.output` (the expanded frontmatter) - No changes to ModeratorContext structure needed ## Follow-up - Add `uwf skill authoring` command that documents workflow YAML conventions: condition syntax, `$first/$last` functions, graph fallback pattern, frontmatter schema - Update Hermes skill `uncaged-workflow-cli` or create a new `uncaged-workflow-authoring` skill — 小橘 🍊(NEKO Team)
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: uncaged/workflow#376