friend

package
v1.5.2 Latest Latest
Warning

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

Go to latest
Published: Oct 17, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Overview

Package friend is the friend lane client: the part of a friend's supervised hook service (nova-hook.client.<name>) that takes her cards from the sprint server and tells her model once (the card the-friend-lane-is-a-client-with-no-local-state, v1.3, pulled forward by the owner on 2026-10-14).

The server (nova-sprint) owns every friend lane's record: the card it holds, its generation, the lease (lane_at, renewed by every ask and progress, the tick returning a card unheard past LaneGoneAfter), and the finish. The client holds a cache it rebuilds from the server's answers and nothing else: started in an empty directory it asks the server what each lane holds and resumes from that alone. The protocol is the fleet's: one `take --as friend.<name> --lane <n>` per lane (pkg/friend LaneTakeArgv, ParseLaneHold), and the model finishes through the server's own finish verb.

Liveness is the hook record's alone: the client asks, and so renews the leases, only while the model proves (Round's proven). A dead client renews nothing, and neither does a live client whose model stopped answering its challenges: the lease runs out and the server returns the card. The model is tla/FriendLaneClient.tla (OneLanePerCard, FinishedOnce, TakenStaysTaken, RestartResumes, DeadClientReleases, DeadModelReleases, and for the width config.go applies NoLostCard, NoDuplicateHold, DrainNeverTakes, GrowTakes; witnesses MCFriendLaneClientBroken*.cfg).

Index

Constants

View Source
const ConfigEvery = time.Second

ConfigEvery is how often the loop's Apply fetches the canonical row.

View Source
const MaxLanes = 1024

MaxLanes bounds one round's free-lane asks (the sprint server's MaxWidth): a bound on a round against a server that never answers a free lane empty, never a width.

View Source
const Subject = "SPRINT CARDS "

Subject is the subject prefix of the one notice a round's new holds make.

Variables

This section is empty.

Functions

func ConfigArgv added in v1.4.6

func ConfigArgv(name string) []string

ConfigArgv is the canonical read of a friend's row, after the nova-config binary.

Types

type Ask

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

Ask sends one verb to the sprint server and answers what it printed, or its refusal.

type Change added in v1.4.6

type Change struct {
	OK     bool   // intake open at Config.Width; false: intake closed, Why says why
	Config Config // the row applied (when OK)
	Why    string
}

Change is what one Apply changed: the line the loop prints, once per change.

type Client

type Client struct {
	Name  string
	Ask   Ask
	Fetch Fetch
	Dir   string
	// contains filtered or unexported fields
}

Client is one friend's lane client. Name is her name (her row is friend.<name>), Ask the server, Fetch her canonical nova-config row (config.go), Dir the brief cache (a directory the client may find empty at any start). It keeps no width of its own: the lanes that take are the applied row's (Intake), read again every ConfigEvery.

func (*Client) Apply added in v1.4.6

func (c *Client) Apply(ctx context.Context, now time.Time) (Change, bool)

Apply is the one call the loop makes every tick: when ConfigEvery has passed since the last fetch, it fetches the canonical row and applies it, and answers the change when what the client runs by changed (a new width, a fetch that failed, one that answers again), so the caller says it once and asks the lanes on its next round. Nothing to fetch (no Fetch) is a closed intake too: a client with no configuration takes nothing.

func (*Client) Intake added in v1.4.6

func (c *Client) Intake() int

Intake is the lanes that take now: the applied row's width, 0 while no row is applied.

func (*Client) LaneArgv

func (c *Client) LaneArgv(n int) []string

LaneArgv is lane n's ask: the fleet's lane take, its answer as JSON (the LANE line and the card's packet with its brief).

func (*Client) Notice

func (c *Client) Notice(fresh, holds []Hold) (subject, body string)

Notice is the one bus message for a round's fresh holds: its subject and body, the body naming every card the server says she holds now, its brief and the verbs that finish it.

func (*Client) Round

func (c *Client) Round(ctx context.Context, proven bool) (holds, fresh []Hold, errs []error)

Round is one round of the lanes: every lane the server says holds a card of hers is asked (and so renewed), whatever the width now; then, while her held cards are fewer than the applied width (Intake), free lanes are asked in order, each taking her next ready card, until one answers empty (the server had none to give, or its own width bound held). It answers every hold the server names and, of them, the ones this client has not told the model yet (fresh), lane order.

The held lanes are the server's answer to friend cards (each working card's lane). When it does not answer the round is blind: the lane take is the only lane ask the server has (no renew-only form: a free lane's ask is a take, and progress, the one verb that renews a lane without dealing, also stamps the late rule's sign that the card moves, which the client cannot say), so a blind round asks only the lanes the last round found held, and only while their count is within the applied width (Intake above 0): a held lane that freed since then takes at most into a lane she held, never past her width, never while her row is unread. Otherwise it asks nothing and keeps what it last found. The bound: a held lane the client does not know (a fresh client, or one restarted, has found none yet), or one held while she drains past a lowered width or her row is unread, is not renewed while friend cards keeps failing, and its lease (the server's 10m) returns the card if that lasts. A lowered width drains: no lane takes until the held cards are under it, and the held ones finish where they are. A raised width takes on the next round. Not proven, it asks nothing: an ask renews a lease, and only a proving model's lanes are renewed. A lane whose ask fails is skipped this round, its error kept, and takes stop for the round; the server's record stands, and the next round asks again.

func (*Client) Row

func (c *Client) Row() string

Row is her fleet row on the server.

func (*Client) Told

func (c *Client) Told(hs []Hold)

Told marks holds as told to the model (the notice was sent).

type Config added in v1.4.6

type Config struct {
	Width int
}

Config is the part of the friend's nova-config row the runtime applies.

func ParseConfig added in v1.4.6

func ParseConfig(name, out string) (Config, error)

ParseConfig reads nova-config friend show --json for name: its width (a whole number from 1). A refusal, another friend's row or a row with no width is an error: the runtime applies the row as nova-config says it, and never a default in its place.

func (Config) String added in v1.4.6

func (c Config) String() string

type Fetch added in v1.4.6

type Fetch func(ctx context.Context, name string) (string, error)

Fetch reads the friend's canonical nova-config row: what `nova-config friend show <name> --json` printed, or why it could not.

type Hold

type Hold struct {
	Lane  int
	Card  string
	Gen   int
	Epoch uint64
	Kind  string
	Job   string
	Brief string // the cached BRIEF.md, "" when the server sent no brief
}

Hold is one lane's card as the server's answer names it, and where its brief is cached.

Jump to

Keyboard shortcuts

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