Skip to content

Releases: Jason-Vaughan/TangleBrain

v0.15.0

19 Jun 06:03
5fafd3f

Choose a tag to compare

Added

  • Per-parent-task delegation tree (cross-process linkage, scatter-gather roadmap #39 stretch /
    closes #52).
    Each delegated sub-call is now linked back to the specific top-level task that
    spawned it, across the process boundary. The CLI mints a task id per routed task; the
    orchestrator-CLI adapter injects it as TANGLEBRAIN_TASK_ID into the orchestrator's environment
    (only when the delegate tool is injected), the orchestrator forwards it to the MCP delegate child
    it spawns, and run_delegate reads it back to stamp each delegate record's parent_task_id. Task
    records gain a task_id, delegate records gain a parent_task_id (both written only when present,
    so existing records and readers are unaffected). tanglebrain --stats and the rollup gain a
    by_parent grouping — "Linked to: N parent task(s)" — with sub-calls run outside a propagated task
    grouped as unlinked. The linkage was manually verified live through the real claude→MCP-delegate
    boundary
    (the env survives the orchestrator's subprocess hop; the parent and delegate records
    shared the same id) — the orchestrator-forwards-env hop is a load-bearing assumption, not a
    TangleBrain-enforced guarantee, so a delegate that loses the env degrades safely to unlinked (never
    an error). This was the deferred half of the scatter-gather epic whose entry criterion was a
    live-verification spike — now done.
  • Knob panel surfaces the delegation tree. The panel's "Delegated sub-tasks" card now shows a
    Linked to stat (N parent task(s), with any unlinked sub-calls noted) — GUI parity with the
    tanglebrain --stats rollup, so the per-parent-task linkage is visible in the panel, not just the
    CLI. Read-only; no new endpoint (the data already rides view_stats's rollup payload).

Fixed

  • pyproject.toml package metadata carried the purged "cost-tiered / flat-rate subscriptions"
    framing
    that the public-rollout neutralization scrubbed everywhere else (#42). Both the description
    and the cost-tiered entry in keywords (→ local-llm) — the metadata rendered on the repo and any
    package index — now match the neutral positioning used in the README and ARCHITECTURE.md:
    "A local-first, config-driven LLM router across OpenAI-compatible backends you own."

Internal

  • Gated live smoke check for delegate parent-task linkage (closes #55). A TANGLEBRAIN_LIVE-gated
    test routes a delegation-inducing prompt through the real router → orchestrator → delegate_local
    and asserts each delegate record's parent_task_id matches the parent task's task_id — a standing
    guard for the load-bearing "orchestrator forwards env to the MCP child" assumption (it skips, never
    fails, if the orchestrator doesn't delegate that run, since delegation is emergent). Test-only; gated
    off in CI.

v0.14.0 — delegate observability + metering

18 Jun 21:12
e6d8359

Choose a tag to compare

Delegate observability + metering — slice 6 of the scatter-gather roadmap (#39).

Added

  • Delegate observability + metering. Delegated sub-calls are now metered: every run_delegate execution (including each delegate_many item — metered at one seam) is logged as a kind: delegate usage record with its served backend + estimated tokens. tanglebrain --stats and the knob panel gain a "Delegated sub-tasks" breakdown by backend (count, est tokens, informational cloud-equiv).
    • Delegate records are kept out of the "spend avoided" headline so a sub-call's saving is never double-counted against its parent task.
    • Concurrent fan-out appends are serialized by a process-level lock.
    • Records carry a new kind field (task/delegate; older records read as task).
    • The per-parent-task tree (cross-process linkage) is deferred.

This closes the deferred metering noted since the measurement layer landed, and builds on parallel fan-out (#39 slice 3, v0.13.0).

Internal

  • Documented the synthesis/reduce pattern (#39 slice 4): TangleBrain doesn't own the reduce step; the orchestrator synthesises delegate_many results itself, offloading a mechanical stitch via delegate(task=…). No reducer tool ships.

Full changelog: https://github.com/Jason-Vaughan/TangleBrain/blob/main/CHANGELOG.md

v0.13.0 — parallel fan-out

18 Jun 17:48
e83a2a8

Choose a tag to compare

Parallel fan-out — slice 3 of the scatter-gather roadmap (#39).

Added

  • Parallel fan-out (delegate_many). A new MCP tool lets an orchestrator fan several sub-tasks out concurrently in one call and collect them, instead of delegating one at a time. Each item ({prompt, target?, task?, max_tokens?}) routes independently — a batch can mix backends — and runs on a thread pool over the existing sync run_delegate (plain Python, no new deps).
    • Results come back in input order with a per-item status: ok (+text), no_fit (+message), or error (+error). A failing sub-task never sinks the batch.
    • Concurrency is bounded by a system-derived default (os.cpu_count()), an operator override (new delegate_max_concurrency in settings.yaml — pin it to your backend's real parallelism, e.g. OLLAMA_NUM_PARALLEL), and an optional per-call max_concurrency that may lower it.
    • Dispatch + collect only — synthesis stays the orchestrator's job.

Builds on capability-routed delegation (#39 slice 2, v0.12.0). Still ahead on #39: synthesis/reduce, orchestration-tree observability.

Full changelog: https://github.com/Jason-Vaughan/TangleBrain/blob/main/CHANGELOG.md

v0.12.0 — capability-routed delegation

18 Jun 17:17
e52b727

Choose a tag to compare

Capability-routed per-sub-task delegation — slice 2 of the scatter-gather roadmap (#39).

Added

  • Capability-routed delegation. The delegate MCP tool gains a task parameter: an orchestrator can delegate a sub-task by the capability it needs (a good_at tag, e.g. code) instead of naming a backend id, and TangleBrain selects the cheapest can_delegate backend good_at it (local before sub, ties by declared order) — sub-task-level task-fit mirroring the request-level router.
    • Precedence: explicit target id > task capability > free local default.
    • Paid api backends are never auto-selected by task (the paid-is-last-resort invariant) — reach one only via an explicit target.
    • No fit → hand back to the orchestrator. When no backend fits the capability, the tool returns an instruction for the frontier model to handle the sub-task itself (a NoDelegateFit signal caught at the MCP boundary), rather than surfacing a tool error or routing to a poor-fit backend.

Builds on the generalized delegate (#38, v0.11.0). Still ahead on #39: parallel fan-out, synthesis/reduce, orchestration-tree observability.

Full changelog: https://github.com/Jason-Vaughan/TangleBrain/blob/main/CHANGELOG.md

v0.11.0 — generalized/tiered delegate

18 Jun 16:11
f019e05

Choose a tag to compare

First feature release after going public (v0.10.0).

Added

  • Generalized / tiered delegate (#38). An orchestrator can now offload a sub-task to a configured backend, not just the free local model. The tanglebrain-delegate MCP server gains two tools alongside the unchanged delegate_local:
    • delegate(prompt, target?, max_tokens?) — route a sub-task to any roster entry flagged the new can_delegate: true (mirrors can_orchestrate); omit target for the free local model.
    • delegate_targets() — list the configured menu (id, tier, good_at, cost, kind) so the orchestrator picks by fit; the delegate tool's description also enumerates the menu, built at server startup.
    • Targets are invoked as leaves (no recursive delegation); api targets stay behind the billing gate; the menu is secret-safe (never emits a key_ref). Non-local delegate spend is not metered in this version — orchestration-tree observability is tracked on the scatter-gather roadmap (#39), of which this is the first slice.
  • Project logo brands the README and the knob panel.

Changed

  • README restructured around Problem → Solution; surfaces the OAuth-/local-first credential model and prompt-aware routing. Knob-panel header copy refreshed.

Full changelog: https://github.com/Jason-Vaughan/TangleBrain/blob/main/CHANGELOG.md

v0.10.0 — first public release

18 Jun 00:45
be6eb3f

Choose a tag to compare

A local-first, config-driven router across OpenAI-compatible backends you own. TangleBrain
routes each task to a backend you've configured — a local model by default, with optional
authenticated CLIs and your own paid API keys as overflow — and keeps the whole roster in one
plain, editable YAML file. Adding or removing a backend is a config edit, not a code change.

Highlights

  • Local-first routing — ships pointing at a free local model server; nothing leaves your
    machine unless you configure a backend that does.
  • Config-driven roster — every routable backend is one entry in a plain YAML list,
    auto-discovered from $TANGLEBRAIN_ROSTER~/.config/tanglebrain/roster.yaml → the packaged
    example, so a git pull never clobbers your config.
  • Frontier-first orchestration — drive authenticated CLI backends as orchestrators with
    rotation and failover across them for resilience.
  • Local sub-task delegation — an orchestrator can offload bulk sub-tasks to the local backend
    over an MCP tool, then review the results.
  • Optional classifier gate — a cheap local pre-filter can send trivial requests straight to the
    local backend (off by default, fails safe).
  • Measurement — every routed task is logged with an estimated cloud-equivalent "spend avoided,"
    rolled up by tanglebrain --stats.
  • Knob GUI — a localhost panel (tanglebrain-gui) to view the roster, pricing, and rollup, edit
    a focused set of config knobs, and run a prompt.
  • Gated paid-API tier — bring-your-own-key overflow, off by default behind two independent
    switches.

Getting started

Requires Python ≥ 3.10.

make venv
.venv/bin/tanglebrain --local "Write a haiku about local inference."

See the README to add orchestrator backends, ARCHITECTURE.md for
how the pieces fit, and DISCLAIMER.md for the opt-in / bring-your-own-key posture.

For contributors

CI runs the hermetic test suite on every push and PR. See CONTRIBUTING.md
adding a backend is usually a config edit, a great first contribution.

MIT licensed.

v0.9.0 — Local classifier gate (off by default)

17 Jun 16:05

Choose a tag to compare

Added

  • Local classifier gate (plan §6 evolution path), off by default. An optional cheap local classify can now run in front of the router: it rates each request's complexity on free local gpt-oss and sends trivial work straight to free local (skipping the rate-limited subs), while frontier work falls through to the normal frontier-first router — preserving sub rate-limit runway when rotation alone isn't enough.
    • Off by default: new classifier_gate_enabled setting (default false); per-run --gate / --no-gate override. Built ahead of the §8 data trigger, so existing routing is unchanged until enabled.
    • Fail-safe by design: rates task complexity (not "can the local model do it?"), and any ambiguity/error/negation resolves to frontier — the gate can never trap a hard task on local. New tanglebrain/classifier.py; gated work meters as path=gate-local.

Notes

  • 316 hermetic tests pass; independent Critic review found no blockers.
  • The paid-API tier remains hermetically tested but live-unverified by design (anti-key stance) — see #23.

Full Changelog: v0.8.0...v0.9.0

v0.8.0 — Editable roster in the knob panel

17 Jun 14:19

Choose a tag to compare

Completes the deferred half of the C5 knob GUI: the tanglebrain-gui roster card is now editable, comment-preserving, with zero new runtime dependencies.

Added

  • Editable roster in the knob panel (plan §5/§9.2). A focused set of per-entry scalar fields is editable from the panel — enabled, can_orchestrate, budget_usd_month, good_at — each row with its own Save.
    • Comment-preserving, no new deps: a new tanglebrain/roster_edit.py edits the targeted value on the targeted line in place, so every inline comment, blank line, the nested invoke block, and the commented paid-API example survive byte-for-byte — no YAML round-trip library. Adding/removing/reordering entries and editing the invoke block stay hand-edits.
    • Write-safety mirrors the pricing editor: edits are validated and the candidate is re-parsed with the real loader before any write (a surgical slip can never land a malformed roster), the prior file is backed up to <state_dir>/backups/roster-<ts>.yaml, and the write is atomic. The panel sends only changed fields and confirms before overwriting the tracked config/roster.yaml.
    • New views.save_roster_view() + POST /api/roster.

Notes

  • 295 hermetic tests pass; independent Critic review found no blockers.
  • With this, the planned build (C0→C7 plus the deferred GUI roster-editing item) is complete.

Full Changelog: v0.7.1...v0.8.0

v0.7.1 — __version__ no longer drifts

17 Jun 00:56

Choose a tag to compare

Fixed

  • tanglebrain.__version__ now derives from the installed package metadata (importlib.metadata.version) instead of a hardcoded literal, so it always tracks pyproject.toml and can no longer drift from the released version — it had been frozen at 0.1.0 since C1 while releases moved on. Falls back to 0.0.0+unknown when imported from an uninstalled source checkout. Closes #17.

Full Changelog: v0.7.0...v0.7.1

v0.7.0 — Paid-API tier complete (off by default)

17 Jun 00:47

Choose a tag to compare

Completes the paid-API tier (closes #2): an off-by-default, LiteLLM-fronted last-resort tier with full operator visibility. Builds on v0.6.0's gate + adapter (C6a) with last-resort routing (C6b) and panel visibility + a runbook (C6c).

Added

  • C6b — last-resort paid-API routing. The frontier-first router now falls through to a paid tier: api entry as a genuine last resort (plan §6): only after every can_orchestrate sub has failed/exhausted, and only when the api_billing_enabled gate is on. Gate off (the default) → the router never reaches a paid tier. Enabled api entries are tried in roster order; a paid success is metered tier=api/spend_avoided=0 but does not advance the rotation cursor; paid failures fail over with the same [rate-limit] annotation. Requires ≥1 orchestrator (never paid-routes a subless roster).
  • C6c — paid-API visibility + runbook. The tanglebrain-gui knob panel surfaces each entry's enabled kill-switch and budget_usd_month (display-only), plus a Paid-API billing: ON/OFF banner from the global gate. New view_settings() + GET /api/settings (reads only config/settings.yaml; no key file touched). README gains a step-by-step runbook for minting a budget-scoped LiteLLM virtual key on Monad and wiring it via key_ref.

Notes

  • Off by default and safe: paid billing requires the explicit api_billing_enabled gate and a per-entry enabled flag. Custody is LiteLLM-fronted (a scoped virtual key via key_ref); the hard budget cap is enforced LiteLLM-side, not by TangleBrain (v1 decision).
  • 265 hermetic tests pass; each chunk passed an independent Critic review.

Full Changelog: v0.6.0...v0.7.0