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

fleetgoal

package
v0.2.11 Latest Latest
Warning

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

Go to latest
Published: Oct 19, 2026 License: Apache-2.0 Imports: 7 Imported by: 0

Documentation

Overview

Package fleetgoal is the goal executor's mind (design 055): it observes a fleet, judges whether the fleet and each of its agents are on track to their goals, and plans the few messages that keep them moving in order.

PURE, LIKE internal/fleet AND internal/board: no NATS, no clock, no I/O. The actor around it (internal/actors/fleet_goal_executor.go) reads the ledger and the board, hands both in with `now`, and sends what Plan returns. Every verdict below is therefore reproducible in a test to the millisecond, which is the point: a coordinator whose judgement cannot be replayed cannot be trusted to interrupt anyone.

IT READS WHAT THE HUMAN READS. The assessment is built on board.BuildFlow, board.BuildFlowDeps and board.TeamRows — the model behind the team view (t) and the dependency tree — so anything the executor says about a bottleneck or a waiting count can be checked against the screen.

Index

Constants

View Source
const (
	KindReport = "goal-report"
	KindAlert  = "goal-alert"
)

Board post kinds the executor writes.

View Source
const (
	CondDeadlock    = "deadlock"
	CondStressed    = "stressed"
	CondStrayed     = "strayed"
	CondStalled     = "stalled"
	CondBlocker     = "blocker"
	CondBlocked     = "blocked"
	CondUnblocked   = "unblocked"
	CondIdle        = "idle"
	CondProgressing = "progressing"
	CondMet         = "met"
)

Conditions — per member, several may hold; the primary is the first in ConditionOrder that does.

View Source
const (
	StateStarting = "starting" // nobody has declared anything yet
	StateOnTrack  = "on-track"
	StateAtRisk   = "at-risk"
	StateOffTrack = "off-track"
	StateStuck    = "stuck"
	StateMet      = "met"
	StateNoGoal   = "no-goal"
)

Fleet states.

View Source
const (
	KindSequence = "SEQUENCE" // a deadlock: one breaker goes first, the rest hold
	KindHurry    = "HURRY"    // a blocker with waiters: finish this first, give an ETA
	KindWait     = "WAIT"     // a waiter: whom you wait on, until when; do not ask them
	KindShield   = "SHIELD"   // a stressed agent: messages held, one thing to do
	KindRealign  = "REALIGN"  // a strayed agent: back to the goal
	KindPull     = "PULL"     // an idle agent's parent: give it goal work, or pair it
	KindRisk     = "RISK"     // the head: the fleet's state got worse
	KindConfirm  = "CONFIRM"  // the head: every member goal is met; is the fleet's?
)

Directive kinds.

View Source
const Identity = "fleet"

Identity is the board identity the executor posts and sends as. The fleet actor's: the executor is its child, and the flow view draws both as the one `fleet` node. The envelope says which of the two is speaking.

Variables

View Source
var (
	// StressThreshold is the score at which an agent is stressed (§5.1).
	StressThreshold = 3
	// RecentWindow is how far back "recent prompts" reach.
	RecentWindow = 15 * time.Minute
	// WanderWindow bounds the "wandering" signal: task texts declared within it.
	WanderWindow = 30 * time.Minute
	// OverrunGrace is the least slack past an agent's own ETA before it is
	// called an overrun.
	OverrunGrace = 10 * time.Minute
)

Thresholds. Variables, not constants, only so a test can name them; the actor never changes them.

View Source
var (
	// MaxPerHour bounds the executor's messages to one agent.
	MaxPerHour = 4
	// MaxPerHourStressed bounds them for a stressed agent.
	MaxPerHourStressed = 1
	// LadderTop is the highest escalation level: 1 the agent, 2 + its parent,
	// 3 + the head and a board alert for the human.
	LadderTop = 3
)

Budget and ladder. Variables only so a test can name them.

ConditionOrder is the priority of conditions: the most actionable first.

Functions

func FlowPanes

func FlowPanes(f *fleet.Fleet) []board.FlowPane

FlowPanes renders a fleet's members as the flow model takes them, with exactly the pane meta the actors mirror — so the flow the executor builds is the flow the board pane draws.

func Observe

func Observe(mem *Memory, in Input)

Observe records one sample per member in mem. Call it once per cycle, before Assess: stray signals compare this cycle with the previous ones.

Types

type Action

type Action struct {
	Kind  string
	To    string // pane id
	Label string // display name of To
	// About is the agent the directive concerns (== To unless it is a copy
	// to a parent or the head).
	About string
	Text  string
	// Ask: the recipient's next `fleet status` answers it (HURRY, REALIGN,
	// SEQUENCE to the breaker). Otherwise informational: `board ack` closes it.
	Ask   bool
	Level int
	Key   string
}

Action is one directive to send.

type Assessment

type Assessment struct {
	Fleet   string
	BoardID string
	State   string
	Why     []string

	// Pct is the mean declared pct over members with one; -1 when none.
	Pct int
	// Finish is the critical-path finish of the fleet; 0 when unknown.
	// Unknown counts the open paths with no estimate.
	Finish  int64
	Unknown int
	DueAt   int64

	Bottleneck        string // pane id ("" none)
	BottleneckWaiting int

	// Members in chain order — the team view's order.
	Members []MemberAssessment
	// Cycles are deadlocks, each in blocked_by order (pane ids).
	Cycles [][]string
	// Deps is the dependency tree exactly as the views render it.
	Deps []string
	// BoardOK is false when pressure could not be read.
	BoardOK bool
}

Assessment is one cycle's verdict on the whole fleet.

func Assess

func Assess(in Input, mem *Memory) Assessment

Assess judges the fleet. mem must have been fed this cycle by Observe.

func (*Assessment) Member

func (a *Assessment) Member(id string) *MemberAssessment

Member finds a member's assessment by pane id.

type Input

type Input struct {
	Fleet fleet.Fleet
	// Threads is the fleet board's recent window; nil with BoardOK false when
	// the recorder did not answer — pressure is then UNKNOWN, never zero.
	Threads []board.Thread
	BoardOK bool
	Now     int64
	Config  fleet.GoalExec // resolved
}

Input is one cycle's observation.

type MemberAssessment

type MemberAssessment struct {
	PaneID string
	Label  string
	Role   string
	Parent string // pane id; may be outside the fleet

	Primary    string
	Conditions []string

	Work, Task, Activity, Health string
	Pct                          *int
	EtaAt                        int64
	Goal                         *fleet.Goal

	// Waiting is how many distinct agents wait on this one, directly or not —
	// the dependency tree's count.
	Waiting int
	// Waiters are the agents blocked directly on this one (pane ids).
	Waiters []string
	// BlockedBy are its blockers (pane ids, "human", "ext:…").
	BlockedBy []string

	// Pressure, from the board. -1 when the board could not be read.
	OpenPrompts   int
	RecentPrompts int

	StressScore int
	StressWhy   []string
	StrayWhy    []string

	// Finish is when it is expected to be done (critical path); 0 = unknown.
	Finish int64
}

MemberAssessment is one agent's verdict.

func (*MemberAssessment) Has

func (m *MemberAssessment) Has(c string) bool

Has reports whether m has condition c.

type Memory

type Memory struct {
	Samples map[string][]Sample
	Ladder  map[string]*Rung
	Sent    map[string][]int64 // pane -> send times within the last hour
	Cycles  int

	LastState    string
	LastReport   string // the last report's fingerprint
	LastReportAt int64
	IntervalSec  int // the adaptive cadence's current interval
}

Memory is the executor's own state across cycles. In-process: warm-up (Plan's first cycle sends nothing) is the guard against a restarted daemon re-sending everything it said before.

type Plan

type Plan struct {
	Actions []Action
	// Alerts are board `goal-alert` posts (level-3 escalations, waits on the
	// human) — for the human, who reads the board.
	Alerts []string
	// Report is a `goal-report` status post, or "" when nothing changed.
	Report string
	// NextSec is when to look again.
	NextSec int
	// Held counts directives the budget deferred to a later cycle.
	Held int
}

Plan is one cycle's output.

func MakePlan

func MakePlan(a Assessment, in Input, mem *Memory) Plan

MakePlan plans one cycle. It mutates mem (ladder, budget, cadence, report).

type Rung

type Rung struct {
	Fingerprint string
	Level       int
	SentAt      int64
}

Rung is one (kind, agent) on the escalation ladder.

type Sample

type Sample struct {
	At       int64
	Work     string
	Task     string
	Activity string
	Pct      int // -1 when none declared
	Updated  int64
}

Sample is one observation of a member, kept across cycles: drift is only visible over time.

Jump to

Keyboard shortcuts

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