Skip to content

Releases: loncadev/baron

v0.42.0 — what a day on a real Azure DevOps project found, fixed

Choose a tag to compare

@keparlak keparlak released this 07 Sep 22:50
53a19d3

What a day of running Baron on a real Azure DevOps project found, fixed.

0.41.0 was dogfooded end to end on a live project — issue, branch, a run that stopped halfway and
was resumed, pull request, merge, sync, close — with the agent driving Baron and a human watching.
Six defects came out of it. Five are fixed here; the sixth is filed with its shape (#223).

A merge is judged after Azure finishes it

Azure answers the pull-request completion request with the PR as it was — still Active — and
merges a moment later. Baron read that answer as the verdict and reported a real merge as
MERGE_FAILED; a user who believed it would have run task-land again against an already-merged
pull request. mergePullRequest now waits for Azure to finish (bounded, 20 seconds, re-reading
the PR each second), returns the merge commit, and — if the wait runs out — says how long it
waited and to read the PR status before retrying.

CI runs are filtered where the provider is

Listing Azure runs by branch fetched the newest N builds and filtered the branch afterwards, so
top was spent on other branches and a build queued a moment ago on the asked-for branch was
invisible: the same query returned nothing at limit 5 and the build at limit 50, and trace said
"no CI run" about a build Baron itself had just triggered. The branch now reaches Azure as a
filter and results come newest-queued first, so runs still queued or running count as the latest.

trace finds the pull request's own builds

Providers build a pull request on a ref of their own — refs/pull/<n>/merge — not on the source
branch, so a trace that asked by branch could never see a PR's validation builds. The ci contract
learns the join (RunQuery.pullRequestId, Run.pullRequestId; the conformance suite pins it), the
Azure adapter maps it to the merge ref, trace asks for the branch and then the pull request, and
when neither has a run it names both places. baron_ci_read op=runs takes pullRequestId too.
The post-merge build on the target branch is not joined yet; #223 says what that needs.

A failed run says where it stopped, and what it had done

Over MCP, a failed recipe run carried its run id only in structuredContent, which the model does
not reliably see; the agent reported "no run id" and read the journal by hand. And a resumed run
that had replayed three steps and then failed returned the error alone — its "Replayed …" lines
were gone, and the agent concluded nothing had been replayed. The error text now ends with the run
id and the exact resume call, and the messages the run produced before it stopped arrive as the
second text block, exactly as they would on success. A provider's own error is wrapped as
RECIPE_STEP_FAILED so it carries the same.

init keeps the credentials template committable

A hand-written .baron/credentials.* in a project's .gitignore also matched
credentials.example, so the template init means to be committed never reached the repository.
init now evaluates the ignore patterns against the template the way git does and appends
!.baron/credentials.example when something would hide it.

What Baron got right on the day

Across three failed resume attempts of the same run nothing was repeated and Azure ended with one
pull request; trace's missing reasons were read correctly by the agent; and when Azure did not
close the item on merge, task-sync-report named it and task-move closed it.

v0.41.0 — resumable runs, trace, an honest handshake

Choose a tag to compare

@keparlak keparlak released this 06 Sep 14:17
c829317

A recipe that fails halfway is now a retry, not a cleanup job; one read says where an item is end
to end; and the server's handshake lists what it actually speaks to.

Every run is journaled and resumable

ship and task-finish mutate several providers in sequence. When the third step failed, the
first two had already happened, and running the recipe again from the top did them again — the
concrete case was a second pull request.

Every run now appends one line per event to .baron/runs/<runId>.jsonl (gitignored; init adds
it): the inputs it started with, each answer, each do step with an idempotency key and the result
it bound, its messages, and the error or the end. The run id is reported on success and on failure
— the CLI prints the exact command to continue, the MCP error carries details.run.

baron run --resume <runId> and baron_recipe_run { resume } restore the inputs and answers
(nothing is asked again), replay every completed step from the journal instead of executing it, and
carry on from the step that stopped. A step's key includes its interpolated parameters, so changed
inputs run again; a changed recipe refuses to resume (RUN_RECIPE_CHANGED); a finished or unknown
run is RUN_NOT_FOUND.

Proven live on Baron's own repository: a recipe that created an issue, commented on it and then
opened a pull request from a branch that did not exist stopped at the PR twice and was resumed
twice; GitHub ended up with one issue, one comment and one pull request. Compensation — undoing
what a run that cannot be completed already did — stays deferred until a real case gives it a shape.

trace: where one item is, in one read

issue.trace in a recipe, baron_issue_read op=trace over MCP: the issue, its canonical branch,
the most recent pull request from that branch in any state with its review and checks, the latest
CI runs on the branch, and the most recent deployment whose ref is the branch — composed from the
ports already bound, joined on the branch name the core already derives. A part that could not be
filled is null and named in missing with the reason: the port is not bound, or the item has
not reached that hop. The tool count is unchanged.

The handshake names every provider and recipe

The server's instructions said "Azure DevOps, GitHub, Slack" and five recipes. Both lists are now
built from the registries, and a test pins that every provider and every built-in recipe appears.

v0.40.0 — Linear browser sign-in, Jira sprints, init recovery, the gate proven

Choose a tag to compare

@keparlak keparlak released this 06 Sep 12:07
9f8f20f

A browser sign-in for Linear that works on a bare install, Jira sprints, a baron init that
recovers from a wrong credential, and the gated-transition contract proven against a real classic
workflow.

0.39.0 was tagged but never published to npm. Everything it would have carried is in this release.

Linear: sign in from the browser, no key to paste

baron init --provider linear now offers to sign you in through the browser instead of asking for
a personal API key — through Baron's own public Linear application, so there is nothing to
register. It is the OAuth authorization-code flow with PKCE: no client secret exists anywhere, and
the token exchange is bound to the process that started the sign-in. The access token Linear issues
lasts a day; the refresh token, its expiry and the application id are stored beside it in
.baron/credentials, and the transport renews the token before it expires (or once, when Linear
refuses it) and writes the rotated pair back — from the MCP server and from baron run alike — so
a sign-in outlasts the day. BARON_LINEAR_CLIENT_ID selects another application; set it to empty
to keep pasting a key, which is narrower than any OAuth scope.

Two things the live run taught, both fixed before shipping: Linear matches the redirect URI
against the application's registered list exactly, port included, so Baron listens on a fixed
port (41765, BARON_LINEAR_CALLBACK_PORT moves it, and a port in use names the way out); and the
page the browser lands on after approving now says who signed in and what to do next, instead of
one bare line of text.

Jira stays on the API token: Atlassian's OAuth requires a client secret and offers no PKCE, so a
shipped CLI cannot hold it honestly.

Jira sprints

Sprints on Jira belong to a Scrum board, not to the project, and live on the Jira Software API
rather than the platform one — which is why the adapter shipped with sprints: false. It now
resolves the project's first Scrum board (or the one JIRA_BOARD names, by id or name), lists that
board's sprints as iterations with the active one as @current, moves an issue into a sprint
through the agile API, and filters a query by sprint. The sprint an issue is in is read from Jira's
sprint field, whose id varies per site and is discovered once from the field catalogue. A project
with no Scrum board simply has no sprints.

baron init recovers from a credential the provider refuses

When the provider cannot be read with the credentials just gathered, init says which provider
failed and why, and offers to re-enter that provider's credentials on the spot (current non-secret
values shown so a typo is visible; an empty answer keeps what is there; secrets never echoed),
saves them, and tries again. A --force run, a declined offer, or a second failure stops with
INTROSPECTION_FAILED naming .baron/credentials and the keys to fix. Jira names the site on a
network failure instead of a bare "fetch failed".

Also: init no longer announces "Provisioned N workflow labels" on a provider whose labels exist
by being used. IssuesPort.ensureLabels now resolves to whether anything was provisioned, and the
conformance suite pins the honest answer.

The gate, proven on the classic workflow

A company-managed Jira project on the classic jira workflow gave what the team-managed default
could not: a transition carrying a screen and a status that refuses hops. Through the MCP server,
Resolve without fields was refused with TRANSITION_FIELDS_REQUIRED naming resolution and its
accepted values with nothing written; the retry with fields landed; and a move from Closed was
refused with TRANSITION_NOT_PERMITTED naming Reopened as the one hop allowed. Nine checks, nine
passes, no code change needed.

What was run before publishing

The whole path as a user would — a publish-equivalent tree from a throwaway copy, a fresh
project, a private throwaway repository, init and doctor, every task-* recipe, the MCP
server over JSON-RPC, a headless Claude Code session with the plugin skills, and the Docker image.
The Linear sign-in was then run live against a real workspace: approval, renewal before expiry,
renewal on refusal, a steady-state run that rotated nothing, and a bare install with no
environment at all.

v0.38.0 — Jira Cloud, validated as a user would

Choose a tag to compare

@keparlak keparlak released this 05 Sep 23:20
61b107b

Baron now speaks Jira — and this release was run the way a user would run it before it shipped.

Jira Cloud

npx @lonca/baron-cli@latest init --provider jira. Issues on Jira, branches and pull requests on
GitHub, one contract. Jira is the provider the role contract was hardest to fit, and the reason it
now fits: a status cannot be set on Jira. The workflow permits some transitions from the issue's
current status, and a transition may carry a screen that demands fields. The adapter reads both
from Jira's transitions endpoint, and the core verifies against them before writing
TRANSITION_NOT_PERMITTED names what the workflow would accept, TRANSITION_FIELDS_REQUIRED names
every field a screen wants, and the caller passes them back as fields.

Roles key on the status name, so a confirmed policy.json reads "In Review" rather than an
id. Jira's three categories (To Do / In Progress / Done) cannot tell in_review from
in_progress, so baron init proposes from names and you confirm. Sprints are declared
unsupported for now (they live on the Jira Software agile API); the gap policy decides. The
setup walkthrough is transcribed
from a real run.

Found by running it as a user

Before publishing, the whole path was driven from a publish-equivalent tree on a fresh project —
init, doctor, every task-* recipe with Jira issues and a private GitHub repository, the MCP
server over JSON-RPC, a headless Claude Code session using the plugin skills, and the Docker image.
It found four things the test suites could not, all fixed here:

  • task-land no longer dies on a private repository with a fine-grained token. The check-runs
    403 had been translated into a CredentialPermissionError before the fallback to Actions runs
    and commit statuses could see it, so the fallback never ran. Public repositories hid this: their
    check runs are readable without any permission. It now warns with the exact remedy and lands.
  • task-sync-report reports "merged but still in review". Jira does not close an item when its
    PR merges, so that is the ordinary aftermath of every land there — and the sweep was silent about
    it. A third drift class, auto-fixable with task-move to done.
  • The proposal reads Jira correctly. Its unordered statuses handed in_progress the review
    state, and a "Subtask" listed before "Task" took the task role. Fixed in the core, with the real
    site's introspection as the regression test.
  • A wrong JIRA_SITE is refused by name, with the shape it wants, instead of a raw fetch error.
    A host without a scheme is accepted.

Also: baron_native_request works on Jira, and the transition tool no longer promises that stray
fields are ignored — Jira refuses a field its screen does not carry, and that refusal is right.

For contributors

Under pnpm 11, pnpm deploy rewrites the workspace manifests in place; RELEASING.md says to deploy
from a throwaway copy, and how the user-journey pass is repeated.

v0.37.0 — a transition can ask for fields

Choose a tag to compare

@keparlak keparlak released this 05 Sep 19:16
8033f91

Baron's role contract now covers the provider it was hardest to fit, and a credential form can no
longer hide a credential file.

A transition can ask for fields

Jira cannot be told a status. You read the transitions its workflow permits from the issue's current
state, perform one, and answer whatever its transition screen demands — resolution, fixVersions
— fields that have nothing to do with the role. The first half (reachable targets, refused with
TRANSITION_NOT_PERMITTED naming what the provider would accept) shipped in 0.34. This release adds
the second.

A transport can now report the fields a move demands, each with required and any allowedValues.
The core checks presence before writing and refuses with TRANSITION_FIELDS_REQUIRED naming
every missing field at once, so a caller asks once and retries rather than learning them one
provider rejection at a time. It checks presence and nothing else: what a field means, and whether a
value is acceptable, stays the provider's.

// baron_issue_move { op: "transition", id, role: "done" }
// -> isError, code TRANSITION_FIELDS_REQUIRED
// structuredContent.details.fields:
//   [{ "name": "resolution", "required": true, "allowedValues": ["Fixed", "Won't Do"] }]
// baron_issue_move { op: "transition", id, role: "done", fields: { "resolution": "Fixed" } }
// -> moved

Recipes take the same fields on issue.transition. Both transport methods are optional, so a
provider that asks nothing implements nothing, and a recipe written for Jira runs unchanged on
GitHub. The in-memory conformance provider now refuses the way Jira does, so the suite can tell a
core that checked from one that got lucky. With this, Gate 3's contract work in the roadmap is done;
the Jira adapter is the first thing to build on it (#173).

Refusals carry data, not only prose

BaronError gained details, and the MCP server puts it in structuredContent. A
TRANSITION_NOT_PERMITTED lists the permitted targets; a TRANSITION_FIELDS_REQUIRED lists the
fields. An agent branches on the payload instead of regexing the message.

A blank credential no longer masks the file

Hosts that present credentials as a form — Docker Desktop's MCP Toolkit among them — pass every
declared variable whether or not the user filled it in. A blank GITHUB_TOKEN used to win over the
value sitting in the mounted project's .baron/credentials, and the server failed for want of a
token it had. An empty variable is now a gap the file may fill; a non-empty one still wins.

This is the groundwork for Baron's Docker MCP Catalog entry, submitted as
docker/mcp-registry#4925. Once it is in, Docker
builds and hosts the image as mcp/baron; docs/mcp.md describes the Toolkit path.

The update notice speaks in both directions

The stale-companion check reported a plugin older than the server and said nothing when it was
newer. 0.36.0 disproved the reasoning behind that: skills ship through the plugin marketplace and the
recipes they call ship through npm, so a plugin ahead of its server is the ordinary state between two
updates — and a 0.36 skill calling a recipe a 0.35 server has never heard of fails with an error that
explains nothing. Both directions now speak, with opposite remedies.

For contributors

The toolchain moved to pnpm 11. Developing needs Node 22+; the runtime floor for the published
packages stays Node 20.

v0.36.0 — a recipe can sweep

Choose a tag to compare

@keparlak keparlak released this 21 Aug 17:48
27c9b1e

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 ask inside 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 still in_progress whose branch has a merged PR, and items
    in_review with no PR at all.
  • task-reconcile — clears a role label the provider's own state contradicts. One step, with the
    guard that matters: reconcile follows the provider while transition commands 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-move has 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

v0.35.0 — an install that can tell you it is stale

Choose a tag to compare

@keparlak keparlak released this 21 Aug 09:01
be4ee0e

Everything here came out of running Baron on a real project it did not grow up in — a seven-week-old
install on Azure DevOps — and none of it was visible from the codebase alone.

Your installation can now tell you it is stale

The Claude Code plugin pins its skills and steering to a commit and never moves them, while the
same manifest launches the MCP server with npx @latest, which moves on every restart. Nothing
compared the two. Measured on the install that prompted this: skills frozen at July, server at
0.34.0, and 17 of the 21 tool names those skills use no longer existed — the agent was being
handed instructions to call tools the server does not publish, and every one failed at the moment it
tried to act.

The plugin now declares the release its skills came from, and a newer server says so on a tool
result rather than shouting into a startup log nobody reads. It stays silent when the two agree,
when the client is newer, and when nothing is declared at all — warning every hand-wired
.mcp.json would make this the notice nobody believes on the day it matters.

Installs from before this release declare nothing, so the check begins working from this
plugin version onward. Unavoidable for artifacts already shipped, whatever mechanism we picked.

Upgrading a policy is no longer blind

baron init asked "already exists. Overwrite it?" before the proposal existed — and on "no" it
introspected anyway, built the proposal and threw it away. So the one question an upgrade turns on
could only be answered by agreeing to replace the file you were trying to protect.

The proposal now comes first, then what it does to what is already there, then the question:

Against the policy already here:
  ~ role done: {"state":"Resolved"} -> {"state":"Closed","boardColumn":"Resolved"}
  + type initiative -> Epic
  ~ type subtask: Bug -> Task
Overwrite …/policy.json with this mapping? (y/N)

Removals are called out loudest, because those are what an upgrade actually costs you. An unreadable
policy says so rather than printing an empty diff, which would read as two files agreeing when only
one of them was understood.

The steering block also stops landing in the wrong file: it goes wherever it already is, else into
whichever of AGENTS.md / CLAUDE.md the project already keeps. Writing AGENTS.md unconditionally
gave most Claude Code projects a second steering document — two files disagreeing, with the stale
one being the one the harness loads by name.

task-land guards that actually guard

  • It refuses to merge over an explicit rejection. The gate read the checks rollup and nothing
    else, so a pull request a reviewer had rejected merged exactly as readily as an approved one.
  • Azure's checks are readable. They are branch-policy evaluations on a separate API this adapter
    did not read, so every rollup came back unknown and every land there proceeded onto an
    unverified state. Same PR, same call, before and after: rollup: unknown, total: 0 became
    rollup: succeeded, total: 1.

review_required deliberately does not block, and that difference was measured rather than
assumed: a repository where nobody casts a formal vote reports it on every pull request, so refusing
on it would make task-land unusable there. A guard that fires on everything is one that gets
removed.

none and unknown stay distinct throughout — a failed read reports unknown with the provider's
own message, never none, because "no checks" tells a caller the merge is unblocked when Baron
simply could not look.

Also

RELEASING's own instructions unpacked the MCP publisher tarball into the repository root — and that
tarball carries a LICENSE and a README.md, which silently replaced Baron's own. One step before a
release, which is exactly when someone runs git add -A.


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

Full diff: v0.34.0...v0.35.0

v0.34.0 — Linear, and role maps that know about scope

Choose a tag to compare

@keparlak keparlak released this 20 Aug 09:04
deeb28b

Baron's fourth provider, and the first one that did not fit the model it was handed.

Linear

Linear is an issues adapter, conformance-green and live-smoke-tested. It is also the first provider
whose workflow states belong to a team rather than to the project — two teams each own an
"In Progress" and they are different rows — so the role map is now written per scope, keyed by
whatever the provider says identifies a state rather than by its name.

That is a contract change, not an adapter detail, and it is why most of this release lives in the
core:

  • The role map carries scopes, one target per team, and a scope the map does not know is an
    error rather than a fall back to the unscoped default — that default belongs to no team, so
    falling back would send another team's state id to the provider.
  • A transport can report which targets an item can actually reach, and the core checks before it
    writes. Jira will need the same seam.
  • A provider can say what identifies its items in a branch name, so a Linear branch reads
    task/bar-12-… instead of carrying a 36-character UUID.
  • Querying by role expands to one target per scope, and a scope that maps the role not at all is
    reported rather than silently skipped.

Linear has no source control of its own. baron init now offers to take branches and pull requests
from the GitHub repository your git remote already names, and gathers both providers' credentials in
one pass — so an issues-only provider no longer means hand-editing policy.json before the first
recipe will run.

There is a from-scratch Linear walkthrough,
written from a real run against a real two-team workspace.

Things that were quietly wrong

Dogfooding Baron on its own repository found these, and each fix is held by a test that was seen
failing first:

  • doctor reported "no drift" on a scoped provider without checking a single state. It walked
    only the flat states map, which is empty by design on Linear, so a real workspace with seven
    mapped states was reported as six references checked — all of them type roles. A green report that
    checked nothing is worse than a red one.
  • baron init --help ran the setup wizard, up to offering to overwrite policy.json and asking
    for a token. --help was matched only as a command, never as a flag on a subcommand.
  • The policy-to-config bridge dropped scopes, so a scoped map never reached the resolver and
    every Linear install resolved roles against an empty map — while the policy, the proposal, the
    resolver and the adapter were each correct on their own.
  • Baron's labels were created team-scoped and looked up workspace-wide, so they were created
    again on every run.
  • The usage line said --recipe <path> though built-in recipes have been accepted by name since
    0.33.0; the README still listed Linear as a roadmap item after it had shipped; and init printed
    "Next steps" before it had finished working.

Release plumbing

Ten package.json versions were bumped by hand each release, and pnpm sync:server-json re-wrote
the mcp-server manifest on any drift — so the documented release step left the repository failing its
own lint. There is now a bump script (the packages on disk are the list) and a test that holds every
package at one version.


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

Full diff: v0.33.0...v0.34.0

v0.33.0 — recipes by name, a doctor that means it, and the tools the docs promised

Choose a tag to compare

@keparlak keparlak released this 17 Aug 20:16

Four defects were live in the published 0.32.1. This removes them.

  • /baron:task-move failed for every user. The recipe shipped and the skill called it, but it was never registered as a built-in, so it returned RECIPE_NOT_FOUND — while the AGENTS.md steering baron init writes told the agent to prefer it. (#93)
  • baron init wrote tool names the server does not publish into the user's own AGENTS.md, where they survive every upgrade and an agent obeying them asks for tools that are not there. (#94)
  • The quick start's third step was a dead end. The CLI could not resolve a recipe by name, so --recipe <path-to>/task-start.yaml had no path to give. baron run --recipe task-start now works, through the same resolver the MCP server uses. (#95)
  • baron doctor reported OK and exited 0 on a credential it had not verified — a probe that threw was recorded as merely unchecked. A probe that breaks now fails the report; a provider that simply has no probe still passes. (#99)

New

  • baron run --recipe <name> resolves built-ins and project recipes by name, identically to MCP.
  • The GitHub device flow opens the approval page for you. The URL and code are still printed first and never replaced — every reason opening fails is a reason you still need to read them.

Also

Documentation was swept against the code rather than re-read: fifteen dead tool names across a dozen files, a roadmap still advertising 36 tools, an op table missing eight ops that the shipped recipes use, blocked still taught as a workflow role after it became a flag, and a licence NOTICE naming ten packages that were never published. Five tests now tie those documents to the code they describe, so the next drift is a red build rather than a discovery.

Full log: v0.32.1...v0.33.0

Baron v0.1.0 — first public release

Choose a tag to compare

@keparlak keparlak released this 02 Jul 19:15

First public release of Baron — a platform-agnostic work-orchestration layer for AI coding agents: one pane of glass (issues, scm, ci, deploy, notify) across providers, via MCP + CLI.

Install

npx -y @lonca/baron-mcp-server   # MCP server (needs a .baron/policy.json — run baron init first)
npx -y @lonca/baron-cli help     # CLI

Packages (npm)

@lonca/baron-core · baron-providers · baron-recipes · baron-cli · baron-mcp-server · baron-knowledge-loop · baron-adapter-azure-devops · baron-adapter-github · baron-adapter-slack — all 0.1.0, Apache-2.0.

Highlights

  • Capability ports (issues / scm / ci / deploy / notify) bound to providers independently
  • Semantic role layer: agents speak roles (backlog → in_progress → in_review → done), never vendor states
  • Deterministic YAML recipes (task-start, task-finish, ship) runnable as ONE call via baron_recipe_run
  • MCP server + Claude Code plugin with per-recipe skills
  • Azure DevOps ports live-validated; adapters covered by a network-free conformance suite (266 tests)