Help us shape the future of Go! Take the 2026 Go Developer Survey

fleet

package
v0.17.0 Latest Latest
Warning

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

Go to latest
Published: Oct 19, 2026 License: MIT Imports: 12 Imported by: 0

Documentation

Overview

Package fleet reports a daemon's activity to the plane: presence (one upserted row per instance, refreshed on every backlog poll) and iteration history (one append-only row per drain, posted at the boundary the loop just crossed). It is the CLI half of CLA-466; the plane half (CLA-465) stores and renders it on the console's Fleet page.

The one design rule everything here serves: reporting is TELEMETRY, never control flow. A failed or slow report is logged once and dropped; it must never block, delay, or fail the loop, a claim, or a phase. So Send enqueues onto a bounded channel and returns immediately — a wedged endpoint cannot slow the poll it rode in on — and a single background pump does the POSTs, so reports arrive in order and the plane's last-writer-wins presence row is always the newest thing this daemon said.

There is deliberately no retry queue in v1. Presence is corrected by the next poll (at most one idle interval later); an iteration record lost to an outage is gone, which is the honest price of keeping telemetry off the loop's critical path.

Index

Constants

View Source
const (
	StateIdle      = "idle"
	StateIteration = "iteration"
	StateDraining  = "draining"
	StateStopping  = "stopping"
)

The presence states a daemon can report. They are the plane's vocabulary (@clankerbar/shared INSTANCE_STATES) verbatim — the plane is a pipe, not a judge, so the CLI owns the mapping from what its loop is doing to these four:

  • idle alive and polling, holding nothing, spawning normally
  • iteration mid-drain: n is the 1-based iteration number, taskRef the task being worked (empty until a claim has been observed), phase the label of the phase session about to spawn or running
  • draining alive but not spawning new sessions (console pause, fleet pause)
  • stopping shutting down on purpose (STOP/HALT, a marker restart, budget or max-iterations reached, signal); sent as the final beacon
View Source
const (
	OutcomeCheckpoint = "checkpoint"
	OutcomeReleased   = "released"
	OutcomeParked     = "parked"
	OutcomeDead       = "dead"
)

How one iteration ended — the driver's own words for how its loop step finished, mapped from what the loop already knows at the drain boundary (@clankerbar/shared ITERATION_OUTCOMES):

  • checkpoint the drain ended with pushed work recorded and the lease left for a successor session to take over
  • released the claim came back to the queue (handed back by the driver, or consumed by the session settling the task itself)
  • parked the dead-phase retry budget parked the task for the operator
  • dead the drain died: a dead phase ended it, or it failed outright

Variables

This section is empty.

Functions

func Probe

func Probe(ctx context.Context, endpoint, apiKey string) error

Probe asks whether activity reporting is wired and reachable WITHOUT writing anything. It exploits the route's own ordering: auth is checked before body validation, and an empty body is refused 400 after it. So one harmless POST of `{}` distinguishes everything doctor needs:

400            wired: reachable, routed, and the key accepted -> nil
401/403        reachable but the key is rejected/forbidden -> *ProbeError
404            reachable but the plane predates fleet reporting -> *ProbeError
other status   reachable, unexpected answer -> *ProbeError
transport err  unreachable -> plain error

A real beacon is NOT used as the probe: it would upsert a presence row under this machine's instance name with doctor's own state, fighting whatever a live daemon on the same host is reporting.

Types

type Identity

type Identity struct {
	Instance       string // the daemon's name; required
	Host           string // hostname
	Version        string // binary version
	ConfigIdentity string // fingerprint of the effective config in force
}

Identity is what every beacon carries about THIS daemon: who and where it is, what build it runs, and which config is in force. Identity is composed per report by the caller (the loop), not baked into the reporter, because one of its fields — the config identity — changes when a RELOAD swaps the config.

type Iteration

type Iteration struct {
	TaskID          string    // task UUID, when a claim was observed
	TaskRef         string    // qualified ref ("CLA-466"), when known
	Phases          []string  // distinct phase labels attempted, in order
	Sessions        []Session // one per session the drain spawned, in spawn order
	Outcome         string    // one of the Outcome* constants
	DurationSeconds float64   // wall clock for the whole drain
	Tokens          int       // the drain's total reported token spend
}

Iteration is one finished loop step: what ran, how it ended, what it cost.

type ProbeError

type ProbeError struct {
	Status int
	Body   string
}

ProbeError carries the HTTP status of a probe that got an answer the doctor needs to branch on.

func (*ProbeError) Error

func (e *ProbeError) Error() string

type Report

type Report struct {
	Identity
	State      State
	Iterations []Iteration
}

Report is one POST body: identity + current state + any iterations that finished since the last report.

type Reporter

type Reporter interface {
	// Send enqueues one report and returns at once. Under an unresponsive
	// endpoint the queue fills and the report is dropped (counted, mentioned in
	// the next line the reporter logs) rather than awaited. After Close it is a
	// no-op.
	Send(r Report)
	// Close ends reporting. Everything still queued is delivered first (newest
	// first, bounded — a run that ends at a drain boundary must not lose the
	// iteration record that boundary just posted), then r is POSTed
	// synchronously — the run is over, so a short blocking wait costs nothing —
	// and the reporter goes inert: r is the LAST POST it ever makes, so after
	// it, console silence means the daemon is gone rather than stopped talking.
	// Idempotent: only the first call speaks. Used for the `stopping` beacon on
	// shutdown paths.
	Close(r Report)
}

Reporter sends activity reports. Both methods are fail-soft by contract: neither blocks meaningfully, neither returns an error, and neither may be load-bearing for the caller.

func New

func New(endpoint, apiKey string) Reporter

New builds a Reporter. Missing either the endpoint or the key yields a not-wired one, so an operator running without a configured plane is degraded rather than broken.

endpoint is the project-scoped fleet-report URL (`https://…/api/projects/<slug>/fleet/report`).

type Session added in v0.15.0

type Session struct {
	Phase   string // phase label the session ran under
	Harness string // the harness that ran it
	Model   string // resolved model id; "" when the harness default applied
}

Session is one harness session an iteration spawned: which phase it ran, which harness ran it, and the model it was spawned with (CLA-630). The values are exactly what the loop's spawn line prints — the phase label, the phase's resolved harness, and the resolved model after tier resolution and any run-config overlay. Model is the EMPTY string when no model was resolved (the harness default applied); the plane stores that as "not resolved", never a guessed name, so an empty value must ride as empty rather than be filled in.

type State

type State struct {
	Kind    string // one of the State* constants
	N       int    // iteration number, when Kind is iteration
	TaskRef string // task being worked ("CLA-466"), when known
	Phase   string // phase label, when Kind is iteration
}

State is the presence half of a report: what the daemon is doing right now.

Jump to

Keyboard shortcuts

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