statusline

package
v0.14.0 Latest Latest
Warning

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

Go to latest
Published: Oct 12, 2026 License: MIT Imports: 20 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// StateManaged: abcd is here and nobody is waiting.
	StateManaged = mode.Managed
	// StateFacilitator: the loop is parked on the facilitator.
	StateFacilitator = mode.Facilitator
	// StateProductThinker: the loop is parked on the product thinker.
	StateProductThinker = mode.ProductThinker
)
View Source
const ContrastBar = 4.5

ContrastBar is the minimum contrast ratio a presence pair must measure to be allowed to render. See the package comment above for why it sits here.

View Source
const RecordRelDir = ".abcd/development"

RecordRelDir is the durable record's root, repo-relative. Its presence is what says a repository has a record to count: without it the two count elements are switched off rather than rendered as zeros nobody means.

View Source
const Separator = " · "

Separator sits between two elements. It is the same one-line separator the rest of this codebase already uses for a run of short facts (capture's reading positions, lifeboat's coverage line, the intent audit's rollup), rather than a new one invented for this row.

View Source
const SettingsFileName = "statusline.json"

SettingsFileName is its leaf name.

Variables

View Source
var ErrNoCheckout = errors.New("statusline: no checkout git will answer for")

ErrNoCheckout is CheckoutRoot's answer for a directory git places in no checkout, or would not answer for.

View Source
var SettingsDisplay = abcdhome.Display(SettingsFileName)

SettingsDisplay names the file in a diagnostic: the tilde form, never the expanded path, so a message a user pastes into a shell works and no diagnostic carries the caller's home path (iss-81, fsutil.RedactHome).

View Source
var SettingsRelPath = abcdhome.Rel(SettingsFileName)

SettingsRelPath is the user-level setting, relative to the caller's home.

Functions

func CheckoutRoot added in v0.13.1

func CheckoutRoot(ctx context.Context, cwd string) (string, error)

CheckoutRoot is the status line's checkout resolution: git's toplevel for cwd through gitutil.ToplevelContext, which holds the answer to the shape gitutil.Toplevel holds it to, under ctx. It answers the one question the verb asks of gitutil.CheckoutRoot — is there a root, and which — and differs only in being bounded: a context that ends first is returned as its own error (context.DeadlineExceeded, wrapped), never as ErrNoCheckout, so the verb does not mistake a slow git for "not a repository" and run the person's previous command over a checkout abcd manages. A git whose output missed the runner's WaitDelay on its retry too (gitutil.ErrGitTimedOut, a loaded machine) is git not answering in time as well, and is returned as itself for the same reason (iss-2610100846469473).

func PaintRole added in v0.13.1

func PaintRole(s State, text string) string

PaintRole paints text in a role's fixed badge pair, padded with one space of fill on each side as the badge pads its word, so another surface that names the role (the status board's view label, spc-2610031844142274) shows the same colours and no second copy of the hexes exists. A state with no fixed pair returns text unpainted. The caller decides whether the terminal can show it.

func ReadSettingsFile

func ReadSettingsFile(home string) (raw []byte, why string, err error)

ReadSettingsFile performs the trust-boundary read of the user-level setting at path. It is the ONE reader of that file: Load reads through it to render the row, and ahoy's install and uninstall steps read through it to record and restore the previous command. The second consumer is why it is exported. `previous_command` is a shell command the harness runs on every refresh, and a reader that took it from a file others can write, or that is not the caller's own, would hand the harness a command somebody else chose — the guard has to be the same guard wherever the file is read, or the weakest reader is the one that runs.

Three outcomes, and the caller phrases the consequence of each:

  • (nil, "", nil): there is no file — the ordinary case, not a diagnostic;
  • (nil, why, nil): a file is present but is NOT the caller's word — not a regular file, writable by group or others, or owned by another uid — and why says which, as a clause after the file's name ("it is writable by others, ..."). Nothing is read from such a file: a caller that renders substitutes the defaults, a caller that would write refuses;
  • (nil, "", err): a file that IS the caller's word cannot be read (over the cap, an I/O error). The error names the file in tilde form.

The guard is the one every home-scoped declaration uses, because it IS that read: fsutil.ReadHomeDeclaration, which opens ~/.abcd.noindex through fsutil.OpenHomeScope (a symlinked ~/.abcd.noindex refused, fsutil.HomeScopeLink's rule) and then judges the file on that descriptor — lstat, the three refusals above, the open, and os.SameFile tying the bytes to the lstat that was judged — under the byte cap. A file renamed into place after any look by path is judged as itself or not read at all, never read on the strength of a judgement made about the file it replaced (iss-2609290656491358).

Types

type Counts

type Counts struct {
	Intents int `json:"intents"`
	Issues  int `json:"issues"`
}

Counts is the record half: open issues, and intents not yet shipped.

Zero is a fact about the record, not an absence, so a zero count renders. A caller that has no record to count switches the two elements off rather than passing a zero it does not mean.

type Element

type Element struct {
	Key      ElementKey `json:"key"`
	Rendered string     `json:"rendered"`
	Plain    string     `json:"plain"`
}

Element is one rendered slot of the row: what it is, how it looks with colour, and how it reads without.

Two forms rather than one because two consumers need different things from the same words. The status verb prints Rendered into a surface that interprets escapes; the `/abcd` board — the fallback where a host has no status surface — prints Plain. Neither invents the text.

type ElementKey

type ElementKey string

ElementKey names one element of the row. The keys are also the names the per-element switches carry in the user-level setting, so a switch and the thing it switches cannot drift apart.

const (
	KeyPresence ElementKey = "presence"
	KeyRepo     ElementKey = "repo"
	KeyBranch   ElementKey = "branch"
	KeyModel    ElementKey = "model"
	KeyContext  ElementKey = "context"
	KeyFiveHour ElementKey = "five_hour"
	KeySevenDay ElementKey = "seven_day"
	KeyIntents  ElementKey = "intents"
	KeyIssues   ElementKey = "issues"
)

func Order

func Order() []ElementKey

Order returns the fixed element order as a copy the caller may mutate.

type Input

type Input struct {
	State   State   `json:"state"`
	Repo    Repo    `json:"repo"`
	Payload Payload `json:"payload"`
	Counts  Counts  `json:"counts"`
}

Input is everything renderRow reads.

type Pair

type Pair struct {
	Foreground string `json:"foreground"`
	Background string `json:"background"`
}

Pair is a badge's foreground and background, as hex.

type Payload

type Payload struct {
	// Model is the model's display name, falling back to its identifier when
	// the harness supplies only that. Sanitized.
	Model string `json:"model,omitempty"`
	// ContextPct is the percentage of the context window in use.
	ContextPct *float64 `json:"context_pct,omitempty"`
	// FiveHourPct and SevenDayPct are the percentages of the five-hour and
	// seven-day usage windows consumed. Either may read above 100.
	FiveHourPct *float64 `json:"five_hour_pct,omitempty"`
	SevenDayPct *float64 `json:"seven_day_pct,omitempty"`
	// Cwd is the directory the harness is standing in: the payload's `cwd`,
	// falling back to `workspace.current_dir`, empty when neither is supplied.
	// It exists so the status verb can resolve the checkout the HARNESS is in
	// rather than the one its own process happens to be in, and it is used for
	// filesystem resolution only — never rendered, never echoed, so it is not
	// sanitised and its tag keeps it out of every JSON envelope.
	Cwd string `json:"-"`
}

Payload is the parsed harness payload: what the four payload-sourced elements need, and nothing else. A nil pointer, or an empty Model, means the harness did not supply the field.

func ParsePayload

func ParsePayload(data []byte) (Payload, error)

ParsePayload reads the harness's status payload.

It refuses anything that is not a JSON object, the truncated stdin and the empty read included: a front door that mistook those for an empty payload would render a row that silently lost four elements, which is exactly the plausible-wrong-answer failure the drop rule exists to make visible. A caller that wants a row without payload elements passes a zero Payload.

type RGB

type RGB struct{ R, G, B uint8 }

RGB is one 8-bit-per-channel colour.

func (RGB) Luminance

func (c RGB) Luminance() float64

Luminance is the WCAG relative luminance of a colour, 0 for black and 1 for white.

type Repo

type Repo struct {
	Name   string `json:"name"`
	Branch string `json:"branch"`
}

Repo is the repository half of the render's input: the two facts that come from the checkout rather than from the harness or the record.

type Result

type Result struct {
	State State    `json:"state"`
	Row   Row      `json:"row"`
	Notes []string `json:"-"`
}

Result is what Compose returns: the state the badge reports, the row, and the notes the composition had to make on the way.

Notes are the out-of-band channel the rest of core uses (rules.Resolve, history.Resolve, LoadFrom here): a count the readers could not take is dropped from the row and NAMED, because a row that silently lost an element is exactly the plausible-wrong-answer the drop rule is meant to make visible. Core never prints; the front door puts them on stderr.

func Compose

func Compose(root string, p Payload, set Settings) (Result, error)

Compose renders the row for an already-resolved checkout root.

The caller resolves the root (CheckoutRoot, or gitutil.CheckoutRoot) and decides whether the repository is managed before calling; Compose takes the root as given. The state is read from the mode store, and a store that cannot be read — a fourth word, a symlink, a device — is an ERROR rather than a quiet badge, for the reason mode.ReadAt gives: somebody wrote something there, and reporting "nobody is waiting" over it would hide the parked stop the badge exists to show.

The branch comes from git: the symbolic ref's short name, or the short sha on a detached HEAD, or nothing (the element drops) when git will not answer. The counts are the record's folder counts (see the package comment), and are switched off in a repository that has no record. The settings are copied before any switch is thrown, so the caller's own Settings are never mutated.

Compose asks git with no deadline of its own; ComposeContext is the same composition with git bounded by ctx, which is what the status verb calls.

func ComposeContext added in v0.13.1

func ComposeContext(ctx context.Context, root string, p Payload, set Settings) (Result, error)

ComposeContext is Compose with every git question bounded by ctx. A git that has not answered when ctx ends is killed and its element drops, exactly as it drops when git will not answer at all, so a slow branch costs the row its branch and nothing else: the badge, the repository and the counts still render (iss-2610050556383525).

type Row

type Row struct {
	Elements []Element `json:"elements"`
}

Row is the composed line: elements in order, ready to join. It is deliberately not a string — a front door that received a string would have to parse it back apart to reuse a part of it, and the board does exactly that.

func (Row) Element

func (r Row) Element(k ElementKey) (Element, bool)

Element returns the element with the given key.

func (Row) Empty

func (r Row) Empty() bool

Empty reports whether the row carries nothing at all, which is what an unmanaged repository and a switched-off setting both produce.

func (Row) Plain

func (r Row) Plain() string

Plain is the row without colour, for the board and for anything that must read the row back.

func (Row) String

func (r Row) String() string

String is the row with colour, for a surface that interprets escapes.

type Settings

type Settings struct {
	SchemaVersion int `json:"schema_version"`
	// Disabled is the off switch: abcd contributes nothing anywhere.
	Disabled bool `json:"disabled"`
	// Elements switches each element after the badge on or off. The badge is
	// element one and is not switchable, so a key for it is ignored.
	Elements map[ElementKey]bool `json:"elements"`
	// Presence is the presence badge's pair. Held to ContrastBar at read time.
	Presence Pair `json:"presence"`
	// PreviousCommand is the status command the harness was pointed at before
	// abcd took the row, recorded at install and restored at uninstall. It is
	// what makes "managed repositories only" true under a single harness-wide
	// setting: outside a managed repository the status verb runs it with the
	// same payload, so the user's own line is unchanged everywhere else.
	PreviousCommand string `json:"previous_command"`
	// Installed reports whether these settings were READ FROM A FILE the caller
	// wrote, as against merged over an absent one. It is never serialised: it
	// is a fact about the load, not a setting. The set form of the mode verb
	// needs it (ac-7): "the host has no status surface" is this being false, or
	// Disabled being true, and a load that merged defaults over nothing is
	// otherwise indistinguishable from one that read a file holding them.
	Installed bool `json:"-"`
}

Settings is the user-level configuration of the row.

func Defaults

func Defaults() Settings

Defaults returns a deep copy of the binary-bundled defaults, safe for the caller to mutate.

func Load

func Load() (Settings, []string, error)

Load reads the user-level setting from the caller's own home.

func LoadFrom

func LoadFrom(home string) (Settings, []string, error)

LoadFrom reads the setting from an explicit home, merges it over the bundled defaults per field, and returns the result together with the notes the read had to make.

The notes are the out-of-band diagnostic channel this codebase already uses for exactly this (rules.Resolve, history.Resolve): core never writes to a stream, so a declaration it declined to honour is RETURNED for the front door to print on stderr. A refusal that printed nothing would be indistinguishable from a setting that was taken.

func (Settings) Enabled

func (s Settings) Enabled(k ElementKey) bool

Enabled reports whether an element renders. The badge always does.

type State

type State = mode.State

State is what the badge is reporting. It is the stored mode's own type (`.abcd/.work.local/mode`, one line, spc-70): mode OWNS the vocabulary — the three words, their parse and their store — and this package holds only the render's view of it. The alias keeps the render's API and tests in their own words while making the two packages' states the same type by construction, so a state read out of the store reaches renderRow without a conversion that could drift. Importing a type is not touching a store: the render stays pure, and mode never imports this package.

Jump to

Keyboard shortcuts

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