Skip to content

v0.4.0 — Manager tier (3-level hierarchy)

Choose a tag to compare

@a-radwan-20 a-radwan-20 released this 15 Jun 13:18
· 38 commits to main since this release

Manager tier — 3-level hierarchy

The mission engine grows a middle tier: supervisor → manager → worker. Previously every plan step dispatched directly to a worker; now a step can carry a list of sub-steps and be delegated to a manager that decomposes and aggregates them.

How it works

A mission.Step can now carry a SubSteps []Step list, marking it a grouped step. When the supervisor encounters one:

  1. It routes the grouped step to the mission's new manager_dispatch topic (instead of the worker dispatch topic), with the sub-step list JSON-encoded in the dispatch payload.
  2. A Manager consumes it, decomposes the sub-step list, and dispatches each sub-step to the same worker pool the supervisor uses.
  3. The Manager awaits each sub-step result (sequentially), then aggregates the outputs — one sub_id: output line each — into a single parent-level Result.
  4. The supervisor sees one "group complete" result for the parent step and continues, exactly as if a worker had handled it.

A single failing sub-step terminates the group with a parent-level error, which the supervisor treats like any other step failure (fail the mission, or replan if a Replanner is configured).

What's new

  • mission.Step.SubSteps []Step — rides in PlanJSON, no schema migration. omitempty keeps existing plans parsing identically.
  • internal/agent/manager — new package implementing the Manager role (competing-consumer subscription, decomposition, sequential sub-step execution, output aggregation).
  • Supervisor routingrunStep and the parallel dispatch loop route grouped steps to the manager; a hydrateSubSteps helper merges SubSteps from PlanJSON onto runtime steps by ID.
  • missionruntime spawns one Manager per mission alongside the supervisor + worker. It parks idle (one goroutine) for plans with no grouped steps.

Fixed

  • mission.Manager.setPlan now allocates step IDs before marshaling PlanJSON. Previously IDs were allocated after serialisation, so a caller passing empty IDs got a PlanJSON whose parent IDs didn't match the allocated mission_steps rows — harmless for leaf-only plans, but it would have silently broken the manager tier's by-ID hydrateSubSteps match. Sub-steps now get IDs allocated too.
  • Toolchain bumped to go1.26.4 — resolves two stdlib CVEs (GO-2026-5039 net/textproto, GO-2026-5037 crypto/x509) flagged by govulncheck against go1.26.3. govulncheck ./... now reports no vulnerabilities.

Scope (deliberately deferred)

  • One level of delegation only (supervisor → manager → worker). A sub-step cannot itself carry SubSteps — no recursive manager nesting.
  • Sub-step execution within a group is sequential. Parallel sub-step dispatch is a follow-up.

Compatibility

Fully backwards compatible. Plans with no grouped steps dispatch every step directly to a worker, exactly as in v0.3.x. No config flag, no migration, no wire-format change.

Tests

5 new manager-package tests (delegate-and-aggregate, sub-step failure, malformed/empty sub-step lists, two managers competing) + 3 new supervisor e2e tests (full 3-tier delegation, leaf-only-needs-no-manager backwards compat, group failure fails the mission). Full repo go test -race -count=1 ./... passes across all 128 packages; cross-compiles clean for linux/arm64 + windows/amd64 under CGO_ENABLED=0.

Full changelog: https://github.com/LumabyteCo/aibutler/blob/main/CHANGELOG.md