v0.36.0 — a recipe can sweep
Baron's claim is that a workflow is enforced by the engine, not by an agent behaving well. This
release closes the hole in it.
A recipe can walk a list
The grammar was ask / do / require / message — every one single-shot. So a workflow that
sweeps N items could not be written at all, and the one sweeping workflow Baron ships (task-sync)
lived as prose in a skill, improvising primitive calls.
On an installation that sets policy.mutations.channel to recipe-only that prose could fix
nothing: every mutation it prescribed was refused, and the refusal told the caller to "find the
recipe that covers this" — which did not exist.
- for_each: ${inProgress}
as: item
collect:
as: mergedButOpen
from: "${item.key}"
when: { truthy: "${merged.id}" } # collect the ITEM, decide on what the PROVIDER answered
steps:
- do: scm.pr.find
as: merged
with: { sourceBranch: "${item.branchName}", state: merged }Three refusals came with it, each a closed footgun rather than a preference:
- Iteration bindings do not leak. Reading
${merged}after the loop gets nothing, not whichever
element happened to be last — a bug that reads as data, since the value is real and merely wrong. - A non-list is an error, not an empty run. Quietly doing nothing is how a sweep reports "all
clear" for a board it never read. - No
askinside a loop, no loop inside a loop. Asks are hoisted so a caller can supply them
upfront, which is what makes a recipe runnable in one shot; an ask in a loop is invisible to that
and asked once per element.
task-sync has recipes to run
Reading what the skill actually needed changed the shape of the fix. It detects, shows a table, asks
for a batch confirmation, then applies — and a recipe runs one-shot with its inputs supplied upfront,
so a confirmation that depends on what the sweep found cannot be a recipe step at all.
The split that does work is the one the architecture already wanted: the drift rule goes in YAML,
where the engine enforces it; asking a human stays in the skill, which is the part only an agent can
do.
task-sync-report— sweeps and reports. Read-only by construction, not by promise: there is no
mutating step in it. Reports items stillin_progresswhose branch has a merged PR, and items
in_reviewwith no PR at all.task-reconcile— clears a role label the provider's own state contradicts. One step, with the
guard that matters:reconcilefollows the provider whiletransitioncommands it, so it
refuses on an item the provider never closed rather than clearing a label on the strength of
nothing.- The class-A fix needed no new recipe: it is a forward move, which
task-movehas always done.
Class B — in review with no pull request — is reported and never fixed. A wrong branch, a force-push
and a hand-moved card look identical there and want different answers.
Verified against a live Linear install under recipe-only, the exact policy that used to make this
dead. That run also caught a wording bug before release: the "no drift" line fired over six drifted
items, because a condition holds one key and cannot AND two findings. It now says which finding it
speaks for.
Install: npx -y @lonca/baron-cli@latest · npx -y @lonca/baron-mcp-server@latest
Claude Code: /plugin marketplace add loncadev/baron then /plugin install baron@baron
The skills ship through the marketplace and the recipes through npm. Update both — a plugin newer
than its server holds skills calling recipes the server does not have yet.
Full diff: v0.35.0...v0.36.0