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 ¶
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
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 ¶
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 ¶
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 ¶
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.
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.