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

fleet

package
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Aug 15, 2026 License: MIT Imports: 25 Imported by: 0

Documentation

Overview

Package fleet turns an operator's plan into a working agent team.

The generating model NEVER writes files. It proposes a manifest; this package validates it and writes the tree. Two reasons that split matters:

  • `.claude/` is a protected path. Writes there are not auto-approved in default or acceptEdits mode and are denied outright in dontAsk, and `permissions.allow` does not pre-approve them. Making it work would mean granting bypassPermissions to a session that just ingested an untrusted operator plan.
  • Writing from Go makes the namespace contract mechanical: every generated file is recorded, so a later regeneration can tell its own output from something a human edited.

Index

Constants

View Source
const (
	// MaxPlanIssues caps how many issues one plan may spawn. A vague plan can
	// decompose into fifty items, which is fifty body sessions and a board
	// full of half-guessed work — a bill and a backlog nobody agreed to. The
	// cap is exported so the wizard can name it when reporting that it bit;
	// silent truncation would leave the operator believing the plan produced
	// exactly what they see.
	MaxPlanIssues = 15
)
View Source
const RosterBudget = rosterTimeout + 5*time.Minute

RosterBudget is how long a caller should allow phase 1 before concluding it hung: the session's own cap plus margin for spawn and parse.

Variables

This section is empty.

Functions

func PhaseBudget added in v0.1.1

func PhaseBudget(remaining int) time.Duration

PhaseBudget is how long a caller should allow the write phase given how many items REMAIN. It budgets remaining work, not the whole run: the wizard re-arms its watchdog with this on every completion, so a big fleet earns time by making progress while a hung one still dies within a single wave.

Types

type AgentSpec

type AgentSpec struct {
	Slug        string `json:"slug"`
	DisplayName string `json:"display_name"`
	// Description is the delegation trigger — it is what the router matches on,
	// so a vague one makes the agent unreachable.
	Description string   `json:"description"`
	Role        string   `json:"role"`  // orchestrator | builder | advisor | reviewer
	Model       string   `json:"model"` // haiku | sonnet | opus | inherit
	Areas       []string `json:"areas"`
	Tools       []string `json:"tools"`
	Skills      []string `json:"skills"`
	Persona     string   `json:"persona"` // the system prompt body, markdown
}

type AgentsService

type AgentsService struct {
	// contains filtered or unexported fields
}

func NewAgentsService

func NewAgentsService(db *sql.DB, log *slog.Logger) *AgentsService

func (*AgentsService) Routes

func (s *AgentsService) Routes(r chi.Router)

type Generator

type Generator struct {
	// contains filtered or unexported fields
}

Generator turns a plan into a fleet.

func NewGenerator

func NewGenerator(db *sql.DB, log *slog.Logger, root string) *Generator

func (*Generator) Generate

func (g *Generator) Generate(ctx context.Context, fleetName, plan, model string, onProgress Progress) (*Manifest, float64, error)

Generate runs both phases, writes the tree and persists the fleet.

Durability contract: the roster is persisted the moment it is decided, and every persona and skill body the moment its session returns. A run that dies at agent 20 of 27 leaves 20 personas in the database, and the next call with the same plan resumes at agent 21 — it re-runs neither the roster session (re-deciding could produce a different team than the personas already written) nor anything already on file. Pressing Generate twice is free.

func (*Generator) GenerateIssues added in v0.1.1

func (g *Generator) GenerateIssues(ctx context.Context, fleetName, plan string, onProgress Progress) (created, dropped int, spent float64, err error)

GenerateIssues breaks the plan into board issues assigned to the fleet.

Durability contract, same as Generate: the decided list is persisted as skeleton rows the moment phase 1 returns, and each body the moment its session returns. A re-run with the same plan re-buys nothing that is already on file — pressing the button twice is free, and a run that died partway resumes at the first missing body.

Every issue lands human_only = true and source = 'import': plan-derived work should be read by a person before agents spend on it, and the board must be able to say which issues a plan produced versus what a human filed. Issues whose area matches an agent's declared areas land 'ready', assigned; an area nobody owns lands in 'triage', unassigned — handing it to whoever looks nearest is how an agent ends up editing a surface it does not own.

Returns how many issues the plan produced on the board and how many the cap dropped; dropped > 0 must reach the operator, not just the log.

type Manifest

type Manifest struct {
	Summary string      `json:"summary"`
	Agents  []AgentSpec `json:"agents"`
	Skills  []SkillSpec `json:"skills"`
	Notes   []string    `json:"notes,omitempty"`
}

Manifest is what the generator returns.

func (*Manifest) Validate

func (m *Manifest) Validate() []string

Validate normalizes the manifest and reports every problem at once, so a regeneration prompt can be given the full list rather than one error per round.

func (*Manifest) Write

func (m *Manifest) Write(root string) ([]WrittenFile, error)

Write renders the manifest into `<root>/.claude/`.

Generated files land in their own namespace and are recorded in manifest.json, so a later run can distinguish its own previous output from a file a human has since edited — and never clobber the latter.

type Progress

type Progress func(stage string, done, total int, spentUSD float64)

Progress is reported back to the wizard as the phases advance, so a run that takes ten minutes does not look like a hang.

spentUSD is included because a ten-minute run showing $0.00 throughout gives the operator no way to tell a cheap run from an expensive one until it is over — by which point the money is spent.

type SkillSpec

type SkillSpec struct {
	Name        string `json:"name"`
	Description string `json:"description"`
	Body        string `json:"body"`
}

type WrittenFile

type WrittenFile struct {
	Path   string `json:"path"`
	SHA256 string `json:"sha256"`
	Owner  string `json:"owner"`
}

WrittenFile records one file the generator produced.

Jump to

Keyboard shortcuts

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