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
- func ConfigArgv(name string) []string
- type Ask
- type Change
- type Client
- func (c *Client) Apply(ctx context.Context, now time.Time) (Change, bool)
- func (c *Client) Intake() int
- func (c *Client) LaneArgv(n int) []string
- func (c *Client) Notice(fresh, holds []Hold) (subject, body string)
- func (c *Client) Round(ctx context.Context, proven bool) (holds, fresh []Hold, errs []error)
- func (c *Client) Row() string
- func (c *Client) Told(hs []Hold)
- type Config
- type Fetch
- type Hold
Constants ¶
const ConfigEvery = time.Second
ConfigEvery is how often the loop's Apply fetches the canonical row.
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.
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
ConfigArgv is the canonical read of a friend's row, after the nova-config binary.
Types ¶
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
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
Intake is the lanes that take now: the applied row's width, 0 while no row is applied.
func (*Client) LaneArgv ¶
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 ¶
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 ¶
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.
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
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.