Documentation
¶
Overview ¶
Package lookaround collects facts about one project and derives where each of its tasks stands. Collectors (host, tracker, local) fetch and interpret nothing; Derive is one pure function, facts in, rows out, and the only place a stage is decided; the Board is the JSON every renderer reads, docs/board.md its spec and docs/board.schema.json its schema.
Index ¶
- Constants
- Variables
- func AgentFor(id, branch, path string) string
- type Board
- type Branch
- type Facts
- type Findings
- type Inputs
- type Local
- type LocalInputs
- type Next
- type PR
- type PRRef
- type Person
- type Project
- type ReviewFacts
- type Row
- type Source
- type Task
- type Where
- type Who
- type Window
- type Workspace
- type Worktree
Constants ¶
const ( SourceHost = "host" SourceTracker = "tracker" SourceLocal = "local" )
The three sources, in the order the board lists them.
const ( StageAsksWaiting = "asks-waiting" StageBlocked = "blocked" StageReady = "ready" StageInReview = "in-review" StagePROpen = "pr-open" StageImplementing = "implementing" StagePlanned = "planned" StageMergedUnfinished = "merged-unfinished" StageNext = "next" StageDone = "done" )
The stages, in the order the board lists rows.
const ( FromLocal = "local" FromTrace = "trace" FromGuessed = "guessed" )
Where a stage's evidence came from: local state, the traces f10 left on the host, or the host's own facts alone.
const Version = 1
Version is the Board JSON's version; a change to a stage rule or a field's meaning bumps it with the spec.
Variables ¶
var Stages = []string{ StageAsksWaiting, StageBlocked, StageReady, StageInReview, StagePROpen, StageImplementing, StagePlanned, StageMergedUnfinished, StageNext, StageDone, }
Stages is every stage in listing order.
Functions ¶
Types ¶
type Board ¶
type Board struct {
Version int `json:"version"`
GeneratedAt time.Time `json:"generated_at"`
Project Project `json:"project"`
Window Window `json:"window"`
Sources []Source `json:"sources"`
Rows []Row `json:"rows"`
}
A Board is one project's rows, with where each fact came from.
func Derive ¶
Derive turns facts into the board: one row per task or taskless request, its stage decided by the rules docs/board.md lists in order, the first that matches winning, and each rule naming where its evidence came from. It reads no clock and does no I/O: now and since are the board's.
func Unreachable ¶
Unreachable is the board of a project no collector could run for: a checkout whose instructions do not read, or a repository with no host CLI. Every source carries the error, so a reader of several boards sees the project failed rather than empty; a project with no checkout keeps its local source skipped, as a remote read does.
type Branch ¶
type Branch struct {
Task string // the id the branch is linked to, else what its name spells
Riders []string // a bundle's other members
After string // the base task recorded on it
Model string // the agent's model, where start recorded it
}
A Branch is what the local config records on a branch.
type Facts ¶
type Facts struct {
Project Project
Prefix string // the task id prefix, for reading ids off branches and titles
Tasks []Task
PRs []PR
Local *Local // nil when the local collector was skipped or failed
People []Person
Sources []Source
}
Facts is what the collectors found, before any interpretation.
type Findings ¶
type Findings struct {
Round int
Open int // findings with no verdict, or a verdict of ask
At time.Time
}
Findings is a task's latest review round as its findings file holds it.
type Inputs ¶
type Inputs struct {
Project Project
Prefix string
Since time.Time
Host *forge.Host
HostError string // why there is no host, for the source's error
Tasks func(ctx context.Context) ([]Task, error)
// RemoteOpen reports whether the project's declared remote reviewer
// left a review on the request nobody handled; nil declares none. An
// error is a note on the host source, the request kept without it.
RemoteOpen func(ctx context.Context, number int) (bool, error)
Remote bool
Local *LocalInputs
// People is the user's map of one person's identities across the
// sources; nil groups rows by whatever identity each source gives.
People []Person
// Now is the clock; nil is time.Now. A test fixes it so timings are
// stable.
Now func() time.Time
}
Inputs binds the collectors to one project. A nil Host, Tasks or Local is that source absent; Remote skips the local collector on purpose.
type Local ¶
type Local struct {
Runs []state.Run
Worktrees []Worktree
Branches map[string]Branch // by branch name
Plans map[string]time.Time // task id to the plan file's mtime
Archived map[string]bool // task ids whose plan is archived
Findings map[string]Findings // task id to its latest round
Verdicts map[string]string // task id to its latest verdict
Finished map[string]bool // task ids the ledger holds task_finished for
Workspaces map[string]Workspace // worktree path to the Herdr workspace on it
}
Local is what this machine knows: live runs, worktrees, branches, plans, findings, verdicts, what the ledger closed, and Herdr's view.
type LocalInputs ¶
type LocalInputs struct {
Main string // the main checkout
StateDir string // run state files
TTL time.Duration
LedgerPath string // "" reads no ledger
ProjectID string // the ledger's project id
Herdr bool // Herdr is reachable: read its workspaces
}
LocalInputs is where this machine keeps what the local collector reads.
type PR ¶
type PR struct {
forge.PR
Block *trace.State `json:"block,omitempty"`
Trailers []trace.Parsed `json:"trailers,omitempty"`
HeadExists *bool `json:"head_exists,omitempty"` // read for merged requests only
RemoteOpen bool `json:"remote_open,omitempty"` // the declared remote reviewer left one unhandled
}
A PR is a request with what the host says around it.
type PRRef ¶
type PRRef struct {
Number int `json:"number"`
Title string `json:"title,omitempty"`
URL string `json:"url,omitempty"`
State string `json:"state"` // open, merged or closed
Draft bool `json:"draft,omitempty"`
Head string `json:"head,omitempty"`
Base string `json:"base,omitempty"`
Mergeable string `json:"mergeable,omitempty"` // clean, conflicts or blocked
Checks string `json:"checks,omitempty"` // green, red or pending
}
A PRRef is the request a row hangs on.
type Person ¶
A Person joins the identities one person has across the sources: the tracker's name for them, their host login, the emails their commits carry. Every field but Name is optional.
type Project ¶
type Project struct {
ID string `json:"id"` // the normalised remote, `github.com/org/repo`
Name string `json:"name"` // the main checkout's basename
Host string `json:"host,omitempty"` // gh or glab
Checkout string `json:"checkout,omitempty"` // the main checkout; empty with no checkout read
Remote bool `json:"remote"` // local collectors skipped
}
Project names the project the board is about.
type ReviewFacts ¶
type ReviewFacts struct {
Step string `json:"step,omitempty"` // the step the state block names
Round int `json:"round,omitempty"`
Open int `json:"open,omitempty"`
Asks int `json:"asks,omitempty"`
Approvals int `json:"approvals,omitempty"`
ChangesRequested int `json:"changes_requested,omitempty"`
RemoteOpen bool `json:"remote_open,omitempty"` // the declared remote reviewer left one unhandled
}
ReviewFacts is what the row's reviews add up to.
type Row ¶
type Row struct {
Key string `json:"key"` // the task id, else `#<number>`
Task *Task `json:"task,omitempty"`
Stage string `json:"stage"`
StageFrom string `json:"stage_from"`
Who Who `json:"who"`
Where Where `json:"where"`
Review *ReviewFacts `json:"review,omitempty"`
BlockedBy []string `json:"blocked_by,omitempty"`
LastActivity time.Time `json:"last_activity,omitzero"`
Next Next `json:"next"`
}
A Row is one task, or one request naming no task.
type Source ¶
type Source struct {
Name string `json:"name"`
OK bool `json:"ok"`
Skipped bool `json:"skipped,omitempty"`
Error string `json:"error,omitempty"`
Notes []string `json:"notes,omitempty"`
TookMS int64 `json:"took_ms"`
}
A Source is one collector's result: ok with its facts in, failed with its error and nothing from it, or skipped on purpose.
type Task ¶
type Task struct {
ID string `json:"id"`
Title string `json:"title,omitempty"`
URL string `json:"url,omitempty"`
Status string `json:"status,omitempty"`
Priority string `json:"priority,omitempty"`
Assignee string `json:"assignee,omitempty"`
After string `json:"after,omitempty"` // the base its body names
}
A Task is a tracker row.
type Where ¶
type Where struct {
PR *PRRef `json:"pr,omitempty"`
Branch string `json:"branch,omitempty"`
Worktree string `json:"worktree,omitempty"`
Workspace string `json:"workspace,omitempty"`
}
Where the work is.
type Who ¶
type Who struct {
Agent string `json:"agent,omitempty"` // the Herdr agent in its worktree
AgentStatus string `json:"agent_status,omitempty"` // idle, working, done
Model string `json:"model,omitempty"`
Author string `json:"author,omitempty"` // the request's author
Assignees []string `json:"assignees,omitempty"`
Reviewers []string `json:"reviewers,omitempty"` // requested and not yet heard from
Committers []string `json:"committers,omitempty"` // the author emails on the row's commits
// Person is the one name the row groups under: the tracker assignee's,
// else the author's, else the first committer's, each through the
// people map where one matches, else as the source spelled it.
Person string `json:"person,omitempty"`
}
Who is working on the row, and who it waits on.