dispatch

package
v0.15.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 10, 2026 License: Apache-2.0 Imports: 15 Imported by: 0

Documentation

Index

Constants

View Source
const CancelReason = "dispatch-canceled"

CancelReason is the ClosedReason string set on tasks closed by Cancel.

View Source
const SchemaVersion = 1

SchemaVersion of the dispatch manifest format. Bump when the schema changes in a way that breaks consumer skills.

Variables

View Source
var ErrAllWavesComplete = errors.New("dispatch: all waves complete; nothing to do")

ErrAllWavesComplete signals --advance was called after the last wave finished.

View Source
var ErrNoManifest = errors.New("dispatch: no manifest in this workspace")

ErrNoManifest is returned by Read when no dispatch manifest exists in the workspace.

View Source
var ErrWaveIncomplete = errors.New("dispatch: current wave incomplete")

ErrWaveIncomplete signals --advance was called before the current wave's tasks all moved to Closed. The error message names the still-open task IDs.

View Source
var PollInterval = 250 * time.Millisecond

PollInterval is the WaitWorkerAbsent poll cadence. Exported so tests can shorten it; production callers leave it at the default.

Functions

func BuildWorkerCommand

func BuildWorkerCommand(bin string, spec Spec) (*exec.Cmd, error)

BuildWorkerCommand assembles the `bones tasks dispatch worker` invocation with the required flags wired from spec. The parent appends per-result flags (--result, --summary, --claim-from-agent-id) before Start.

Earlier iterations passed these as AGENT_INFRA_* env vars, but the worker's Kong struct never read them — the worker would fail Kong's required-flag validation immediately and the parent would hit its 5s subscribe timeout. Flags-only is the single source of truth.

func Cancel added in v0.6.0

func Cancel(root string, closeTask TaskCloser) error

Cancel removes the manifest and closes any tasks the manifest still references with ClosedReason=CancelReason. Idempotent — no-op when no manifest exists.

func FormatResult

func FormatResult(msg ResultMessage) string

FormatResult serializes msg as a pipe-delimited dispatch payload. The wire format is positional — index 0 is the literal "dispatch-result" tag, 1 is kind, 2 is summary, 3 is branch, 4 is rev, 5 is substrate_error, 6 is substrate_fault. To preserve position when an early field is empty but a later one is set, empty-string placeholders fill the gaps. Trailing empty fields are elided so format output for messages without substrate data is unchanged from the pre-#159 schema.

func Path added in v0.6.0

func Path(root string) string

Path returns the manifest file path for a given workspace root. Honors BONES_DIR (issue #291) via workspace.BonesDir.

func Remove added in v0.6.0

func Remove(root string) error

Remove deletes the dispatch manifest. Idempotent.

func WaitWorkerAbsent

func WaitWorkerAbsent(
	ctx context.Context,
	probe PresenceProbe,
	workerAgentID string,
	deadline time.Duration,
) error

WaitWorkerAbsent polls the substrate's presence view via probe and returns nil once workerAgentID is no longer present, or an error if the deadline elapses first. Used by the dispatch parent to detect worker dropout (heartbeat lapse) before reclaiming the claim.

The probe callback decouples dispatch from coord: tests can pass a closure backed by an in-memory list, and production wiring uses `coord.Coord.PresentAgentIDs`.

func Write added in v0.6.0

func Write(root string, m Manifest) error

Write persists the manifest atomically (tmp+rename). Creates the parent directory if needed.

Types

type BuildOptions added in v0.6.0

type BuildOptions struct {
	PlanPath string
	TaskIDs  map[string]string // slot name → existing task ID (caller-supplied)
}

BuildOptions configures BuildManifest.

type Manifest added in v0.6.0

type Manifest struct {
	SchemaVersion int       `json:"schema_version"`
	PlanPath      string    `json:"plan_path"`
	PlanSHA256    string    `json:"plan_sha256"`
	CreatedAt     time.Time `json:"created_at"`
	CurrentWave   int       `json:"current_wave"`
	Waves         []Wave    `json:"waves"`
}

Manifest is the dispatch contract written by `bones swarm dispatch` and consumed by harness-specific orchestrator skills.

func Advance added in v0.6.0

func Advance(root string, isClosed TaskClosed) (Manifest, error)

Advance promotes the manifest's current wave to the next one if the current wave's tasks are all Closed in bones-tasks KV. Returns the updated manifest. Errors if the current wave is incomplete or if the dispatch is already finished.

func BuildManifest added in v0.6.0

func BuildManifest(opts BuildOptions) (Manifest, error)

BuildManifest parses the plan at PlanPath and produces a manifest with one wave per dependency layer. Caller supplies task IDs (already created in bones-tasks KV); wiring slot → task is the caller's responsibility.

V1: all slots in a single wave (no dependency analysis). Multi-wave support requires plan annotations the validate-plan parser does not yet emit; defer to a follow-up.

func Read added in v0.6.0

func Read(root string) (Manifest, error)

Read loads the dispatch manifest for a workspace root.

type PresenceProbe added in v0.2.0

type PresenceProbe func(ctx context.Context) ([]string, error)

PresenceProbe returns the agent IDs currently present in the substrate. Used by WaitWorkerAbsent to poll for worker dropout without depending on a particular substrate's Presence type.

The standard binding is `coord.Coord.PresentAgentIDs`; tests can pass a closure backed by an in-memory slice.

type ResultKind

type ResultKind string
const (
	ResultSuccess ResultKind = "success"
	ResultFork    ResultKind = "fork"
	ResultFail    ResultKind = "fail"
)

type ResultMessage

type ResultMessage struct {
	Kind           ResultKind
	Summary        string
	Branch         string
	Rev            string
	SubstrateError string
	SubstrateFault string
}

ResultMessage is the dispatch payload posted on the task thread when a swarm slot closes. Kind + Summary are agent intent; Branch + Rev describe a fork outcome. SubstrateError and SubstrateFault are substrate-level signals — populated when bones (not the agent) observed a failure on the close path, so a downstream orchestrator can distinguish "agent didn't accomplish X" from "the substrate blocked the agent from accomplishing X" (#159).

SubstrateError is a free-text message (e.g. "swarm commit failed: nats: no responders"). SubstrateFault is a short category tag (e.g. "commit-failed", "hub-unreachable") for orchestrator-side branching without parsing free text.

func ParseResult

func ParseResult(body string) (ResultMessage, bool)

ParseResult deserializes a pipe-delimited dispatch payload. Missing trailing fields are treated as empty strings so consumers reading the older 3/4/5-field format continue to work. Unknown Kind values are rejected.

type SlotEntry added in v0.6.0

type SlotEntry struct {
	Slot           string   `json:"slot"`
	TaskID         string   `json:"task_id"`
	Title          string   `json:"title"`
	Files          []string `json:"files"`
	SubagentPrompt string   `json:"subagent_prompt"`
}

SlotEntry is one slot's task assignment within a wave.

type Spec

type Spec struct {
	TaskID        string
	Title         string
	Files         []string
	Thread        string
	ParentAgentID string
	WorkerAgentID string
	WorkspaceDir  string
}

Spec is the parent-resolved description of a task ready to dispatch to a worker process. Pure data; no substrate references. The CLI adapter that produced the Task value is the only thing that knows about coord.

func BuildSpec

func BuildSpec(parentAgentID, workspaceDir string, task Task) (Spec, error)

BuildSpec materializes a Spec from a parent agent's view of a dispatchable task. The Task interface keeps dispatch coord-free; CLI callers pass a small adapter wrapping coord.Task.

type Task added in v0.2.0

type Task interface {
	// ID returns the task identifier as a plain string. Whatever
	// coord-side type wraps the ID is converted at the adapter
	// boundary; dispatch carries it as a string.
	ID() string

	// Title is the human-readable title.
	Title() string

	// Files lists the absolute workspace paths the task scopes its
	// work to. The returned slice may be the task's own copy;
	// BuildSpec takes a copy if it needs to mutate.
	Files() []string
}

Task is the dispatch-local view of a coord task record. Defined here (rather than imported from coord) so dispatch can be tested with minimal in-memory fakes and so a future migration to a different task source — a different substrate, a different storage shape — does not ripple through dispatch.

Coord's task type satisfies this structurally via a small adapter at the CLI layer; dispatch never imports coord.Task directly.

type TaskClosed added in v0.6.0

type TaskClosed func(taskID string) (bool, error)

TaskClosed reports whether the task with the given ID is in Closed status. Implemented by the caller (typically a thin shim over internal/tasks).

type TaskCloser added in v0.6.0

type TaskCloser func(taskID string, reason string) error

TaskCloser closes a task with a reason string (e.g. "dispatch-canceled"). Implemented by the caller (typically a thin shim over internal/tasks).

type Wave added in v0.6.0

type Wave struct {
	Wave             int         `json:"wave"`
	BlockedUntilWave int         `json:"blocked_until_wave,omitempty"`
	Slots            []SlotEntry `json:"slots"`
}

Wave is one parallelizable set of slots, blocked until prior waves complete.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL