apiserver

package
v0.38.0 Latest Latest
Warning

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

Go to latest
Published: Sep 9, 2026 License: Apache-2.0 Imports: 8 Imported by: 0

Documentation

Overview

Package apiserver is the Kubernetes-style resource layer of the aeman API: it translates the internal board domain into Card/Sprint/Note/Ordering resources (metadata/spec/status), evaluates LIST selectors for the Team, Me and Triage views, and derives the fields the UI would otherwise compute. It is backend-agnostic: everything works on the domain board snapshot.

Index

Constants

View Source
const HistoryShown = 12

HistoryShown bounds the turns carried per task.

View Source
const TurnsAhead = 13

TurnsAhead is how far the projected turns reach: a quarter, which is as far as anyone plans and further than any board window opens.

Variables

This section is empty.

Functions

func DomainZone

func DomainZone(name string) board.ZoneKey

DomainZone maps an API zone name onto the domain key ("" stays "").

func FilterCards

func FilterCards(b board.Board, sel Selector) []board.Card

FilterCards returns the cards matching the selector, in board order. The view rules delegate to the same domain filters the views always used.

func MarkRecords added in v0.30.0

func MarkRecords(list *CardList, records map[string]bool, asOf string)

MarkRecords stamps the cards that came FROM the past with the moment they are from: everything else in the same listing is today's and stays workable, so the mark is per card.

records is what the day's board took from that evening (board.MergeAsOf's own answer), by card id. Deriving it again from team names loses the cards whose team differs between the two moments — one moved between teams, one of a team renamed since — and such a card comes through LIVE: draggable, editable, and refused by every write door. Which is the refusal G60 names as the thing not to do.

func SemanticZone

func SemanticZone(z board.ZoneKey) string

SemanticZone maps a domain zone onto its API name ("" stays "").

Types

type BoardInfo

type BoardInfo struct {
	Kind     string        `json:"kind"`
	Metadata BoardMetadata `json:"metadata"`
}

BoardInfo is the read-only board resource: identity plus the team roster (the teams that have sprint pointers).

func BoardResource

func BoardResource(b board.Board) BoardInfo

BoardResource is the read-only board identity resource, members without avatars.

func BoardResourceWith added in v0.26.0

func BoardResourceWith(b board.Board, avatar func(login string) string) BoardInfo

BoardResourceWith is BoardResource with the members' avatars resolved by the given hook (nil leaves them empty).

func BoardResourceWithPeople added in v0.26.0

func BoardResourceWithPeople(b board.Board, person func(login string) Member) BoardInfo

BoardResourceWithPeople is BoardResource with the members resolved by the given hook — the forge's avatar and display name for a login (nil leaves both empty). The hook's Login is ignored: the board's login is the identity.

type BoardMetadata

type BoardMetadata struct {
	Title string   `json:"title,omitempty"`
	URL   string   `json:"url,omitempty"`
	Teams []string `json:"teams"`
	// Projects lists the Project board's projects, in board order — the top
	// grouping: a project owns epic columns. (Not the GitHub board, which the
	// caller addresses with owner+board.)
	Projects []string `json:"projects,omitempty"`
	// Processes lists the board's processes in board order, each naming its
	// project. The Process tab reads the full structure from /processes; this
	// is the roster, so a client can tell when it changed.
	Processes []ProcessRef `json:"processes,omitempty"`
	// Deadlines are the deadline lines in board order: the week each one sits
	// on and the project it belongs to. A project holds at most one per week.
	Deadlines []DeadlineRef `json:"deadlines,omitempty"`
	// Epics lists the Project board's columns in board order, each naming the
	// project that owns it. An epic with an empty project belongs to none and
	// shows only in the all-projects view.
	Epics []EpicRef `json:"epics,omitempty"`
	// Members is every distinct assignee on the board — the people roster for
	// pickers (assign, review, view-as) now that clients load one view at a
	// time and cannot derive it from the cards they hold — with the avatar
	// the server's forge adapter resolves for each, so a client never
	// assembles a forge URL of its own.
	Members []Member `json:"members"`
	// Domains are the repositories the visitor can read, primary first: which
	// they may write — a team, project or process is declared in one they
	// pick when more than one is writable — and which members can read each,
	// so a reviewer picker offers only people who will see the card. Absent
	// primary first. The board lists its repositories whatever it spans
	// (G59), so a client compares the stamps it carries against this list
	// and reads a single entry as "no boundaries", never an absent one.
	Domains []DomainInfo `json:"domains,omitempty"`
	// TeamDomains and ProjectDomains name the repository a team or a project
	// was declared in, for the entries that live OUTSIDE the primary — the
	// primary is the default and needs no entry, and a single-repository
	// board names none at all. A client needs them to keep a card's team and
	// project in one repository: the pair cannot both be honoured, so the
	// pickers must not offer it (boardservice.ErrDomainConflict).
	TeamDomains    map[string]string `json:"teamDomains,omitempty"`
	ProjectDomains map[string]string `json:"projectDomains,omitempty"`
	// ProcessDomains does the same for processes: a card may only be tied
	// to a process of its own repository, so the picker needs to know.
	ProcessDomains map[string]string `json:"processDomains,omitempty"`
	// Personal is the visitor's own repository when they linked one: the
	// personal board lives there (view=personal, create with personal=true).
	Personal *PersonalInfo `json:"personal,omitempty"`
}

type Card

type Card struct {
	Kind     string       `json:"kind"`
	Metadata CardMetadata `json:"metadata"`
	Spec     CardSpec     `json:"spec"`
	Status   CardStatus   `json:"status"`
}

Card is a project item as an API resource.

func CardResource

func CardResource(b board.Board, c board.Card) Card

func CardSummaryResource added in v0.16.0

func CardSummaryResource(b board.Board, c board.Card) Card

CardResource maps a domain card onto the API resource, deriving status from the board (reviewedBy needs the linked review card's assignee). CardSummaryResource is CardResource without the card body: the shape of a board row. The description — often the bulk of a card's bytes, and unused by row rendering — stays behind for GET /cards/{uid}; the derived link refs in status keep the row's links indicator honest without it.

type CardDates

type CardDates struct {
	Start  string `json:"start,omitempty"`
	End    string `json:"end,omitempty"`
	Sprint string `json:"sprint,omitempty"`
}

CardDates is the card's date model: its scheduled start, the end of its visible range, and the sprint it belongs to (see docs/dates.md).

type CardLinkRef added in v0.16.0

type CardLinkRef struct {
	Kind   string `json:"kind"`
	URL    string `json:"url"`
	Owner  string `json:"owner,omitempty"`
	Repo   string `json:"repo,omitempty"`
	Number int    `json:"number,omitempty"`
}

CardLinkRef is one extracted reference: a GitHub issue/PR or a plain URL.

type CardList

type CardList struct {
	Kind  string `json:"kind"`
	Items []Card `json:"items"`
	// AsOf is the moment a snapshot listing reflects (RFC3339) — the end of
	// the day it was asked for. Empty on a live listing; a day the history
	// no longer reaches is refused (410) rather than answered.
	AsOf string `json:"asOf,omitempty"`
}

CardList is the LIST response envelope.

func ListCards

func ListCards(b board.Board, sel Selector) CardList

ListCards builds the LIST response for a selector: resources in board order.

type CardMetadata

type CardMetadata struct {
	UID       string `json:"uid"`
	Author    string `json:"author,omitempty"`
	CreatedAt string `json:"createdAt,omitempty"`
}

CardMetadata is the card's identity and immutable facts.

type CardSpec

type CardSpec struct {
	Title string `json:"title"`
	// Description is nil in a summary listing ("body not included" — the
	// row shape) and always present, possibly empty, on a full resource.
	// The distinction is the client's "loaded" marker: only nil means "go
	// fetch the body", so an empty body never reads as a missing one.
	Description *string `json:"description,omitempty"`
	Team        string  `json:"team,omitempty"`
	Zone        string  `json:"zone,omitempty"`
	// Size is what somebody said the card weighs: S, M, L or XL, or absent.
	Size      string   `json:"size,omitempty"`
	Assignees []string `json:"assignees"`
	Progress  int      `json:"progress"`
	Stage     string   `json:"stage,omitempty"`
	// Recurrence, on a recurrent card, is its reseed cycle: "" = every
	// sprint, "week" / "month" = once the interval has elapsed.
	Recurrence string    `json:"recurrence,omitempty"`
	Dates      CardDates `json:"dates"`
	// Week is the week the card is scheduled for, a Monday: its row on the
	// Triage board, and — for an epic card — on the Project board.
	Week string `json:"week,omitempty"`
	// Parked says the card is on its team's SHELF rather than in the plan.
	// Every team has one and nothing declares it. Exclusive with Week — a card
	// is on the shelf or in a week, never both. A parked card is on no day
	// board and out of the Triage strip: parking is the act of reading the
	// inbox and saying "not now".
	Parked bool `json:"parked,omitempty"`
	// Epic and Project are the column the card is filed under ("" = none) —
	// the pair, since epic names repeat across projects. The card's Week is
	// the row, and Dates span the weeks its slot stretches over.
	Epic    string `json:"epic,omitempty"`
	Project string `json:"project,omitempty"`
	// Mirrors are the additional columns the same card stands in — one
	// file, one log, one set of dates, shown in every listed project too.
	// Always the card's own repository (the service admits nothing else).
	Mirrors []board.Placement `json:"mirrors,omitempty"`
	// Process and Task, on a process turn, name the process this card is a
	// turn of and the task it was copied from. A card on the Me or Team
	// board carries them so a person can see what it belongs to without
	// going looking for it.
	Process  string `json:"process,omitempty"`
	Task     string `json:"task,omitempty"`
	ReviewOf string `json:"reviewOf,omitempty"`
	// Parent, on a subtask, is the uid of the card it is grouped under.
	Parent string `json:"parent,omitempty"`
}

CardSpec is the user's intent — everything an edit can change.

type CardStatus

type CardStatus struct {
	Complete   bool `json:"complete"`
	InProgress bool `json:"inProgress"`
	// Overdue: a card that came from a plan — a slot, a process turn, a
	// card scheduled for a week — still open past the day it was owed by. Derived on
	// read from the card's own dates (board.Overdue); never stored.
	Overdue     bool   `json:"overdue,omitempty"`
	ReviewedBy  string `json:"reviewedBy,omitempty"`
	ReviewRound int    `json:"reviewRound,omitempty"`
	// AsOf marks a card served from the PAST: its team's sprint has moved on
	// past the day asked for, so this is what the card was that evening, not
	// what it is. A record — a client shows it as one and does not offer to
	// change it. Absent on every live card, including on the same listing:
	// whether a day is over is each team's own answer (G60).
	AsOf string `json:"asOf,omitempty"`
	// Domain is the repository the card lives in — the store's decision by
	// the inheritance rule, never a client's choice. The store stamps every
	// card, the primary's included, so this normally carries a NAME on a
	// multi-repository board and the client compares it against the primary
	// (cardDomainBadge) rather than reading an empty string as "primary".
	// Empty only where nothing stamped it at all — a board assembled by
	// hand; the git server stamps every card, one repository or many.
	Domain string `json:"domain,omitempty"`
	// DoneAt is the board day the card reached 100 (cleared on reopen) — the
	// personal board shows a done card that day and drops it the next.
	DoneAt string `json:"doneAt,omitempty"`
	// Triage marks a card the Triage board's strip holds: nobody placed
	// it in a week and it is not being worked (B5).
	Triage bool `json:"triage,omitempty"`
	// TriageWeek is the Monday of the column the card stands in on the
	// Triage board: its week, or — for a review card, which has none of its
	// own — the week its own dates fall in. Absent means it stands in none: the strip
	// holds it until somebody says when the work is due (B5).
	TriageWeek string `json:"triageWeek,omitempty"`
	// Due is a RECURRENT card's weeks to come: the ones it comes round in
	// over the planning horizon and no copy of it stands in yet. A team's own
	// repeating work — the weekly report, the monthly invoice — is reseeded
	// by carry-over rather than filed by a process, and the weeks it will
	// land in are as spoken for as a process turn's. Absent on everything
	// else, and on a recurrence with no calendar (per sprint).
	Due []string `json:"due,omitempty"`
	// Cycle is a process TURN's own occurrence: the first and last week it
	// may stand in, both Mondays and both inclusive. A turn belongs to one
	// turn of its process's calendar, and moving it past the next due date
	// would put it where the NEXT turn belongs — the two would then read as
	// one process running twice. Absent on everything that is not a turn,
	// and on a turn whose task has no calendar to reckon with.
	//
	// It is sent rather than derived by the client because the calendar is
	// the server's (board.CycleWindow): a second implementation of "when is
	// this next due" is a second answer waiting to disagree.
	Cycle *CycleWindow `json:"cycle,omitempty"`
	// LeftAt is the board day the × took the card off. On a personal card
	// that is a live rule — the board shows it that day and before, not
	// after; on a team card the × demotes into the previous sprint and this
	// records the day, which a RECORD of that day gives back (G60).
	LeftAt string `json:"leftAt,omitempty"`
	// Links are the references extracted from the card's description —
	// unresolved (no titles or states; GET /cards/{uid}/links resolves those).
	// They ride the status so a summary listing, which omits the description
	// itself, still tells a row it has links to show.
	Links []CardLinkRef `json:"links,omitempty"`
}

CardStatus is derived by the server, never written by clients.

type CycleWindow added in v0.32.0

type CycleWindow struct {
	From string `json:"from"`
	To   string `json:"to"`
}

CycleWindow is the span of weeks a process turn's own occurrence covers, as Mondays, both ends inclusive.

type DayEntries added in v0.26.6

type DayEntries struct {
	Notes  []board.Note
	Events []board.Event
}

DayEntries is one card's notes and events on a day — the service's answer shape, kept here so the resource layer does not import the service.

type DayLogList added in v0.26.6

type DayLogList struct {
	Kind string `json:"kind"`
	Day  string `json:"day"`
	// Cards maps a card's uid to its entries on that day, oldest first. A
	// card that was quiet is present with an empty list; a card the visitor
	// cannot see is absent.
	Cards map[string][]LogEntry `json:"cards"`
}

DayLogList is the GET /logs response: one day's feed, per card. The day board asks it once for every card it shows — a card's own whole history is the other question (GET /cards/{uid}/log).

func DayLogsFrom added in v0.26.6

func DayLogsFrom(day string, per map[string]DayEntries) DayLogList

DayLogsFrom builds the day feed's response from what the service found.

type DeadlineRef added in v0.17.0

type DeadlineRef struct {
	Week    string `json:"week"`
	Project string `json:"project,omitempty"`
}

DeadlineRef is one deadline line: its week and the project it belongs to.

type DomainInfo added in v0.26.0

type DomainInfo struct {
	Name     string   `json:"name"`
	Writable bool     `json:"writable"`
	Members  []string `json:"members"`
	// Personal marks the visitor's own repository, attached for them alone.
	Personal bool `json:"personal,omitempty"`
}

DomainInfo is one readable domain of the visitor's board.

type EpicRef added in v0.17.0

type EpicRef struct {
	Name    string `json:"name"`
	Project string `json:"project,omitempty"`
	// Domain is the repository the column was declared in. The git server
	// names every column, the primary's included; a board assembled by
	// hand may leave the primary's blank. Read it as a NAME to compare
	// against domains[0], never as "absent means primary". A client cannot
	// compute it from the project: the same project NAME may be declared
	// in two repositories with its columns merged under one entry (G13),
	// and it is the COLUMN that decides whether a card may stand in it.
	Domain string `json:"domain,omitempty"`
}

EpicRef is one Project-board column: its name and the project that owns it. The pair travels together because a column is meaningless without knowing which project's grid it belongs in.

type Iteration added in v0.18.0

type Iteration struct {
	UID   string `json:"uid"`
	Week  string `json:"week"`
	State string `json:"state"`
}

Iteration is one spawned card and how it went: "done" when it closed, "open" while it still runs inside its cycle, "late" when it is still open past the point the next one was due.

type LogEntry

type LogEntry struct {
	// Type is "event" or "note".
	Type string `json:"type"`
	ID   string `json:"id"`
	At   string `json:"at,omitempty"`
	// Actor is the event's actor or the note's author.
	Actor string `json:"actor,omitempty"`
	// Event fields (Type == "event").
	EventKind string `json:"kind,omitempty"`
	From      string `json:"from,omitempty"`
	To        string `json:"to,omitempty"`
	// Note body (Type == "note").
	Text string `json:"text,omitempty"`
}

LogEntry is one item of a card's unified activity feed: a recorded event (stage/progress/review/plan change) or a work note, in one timeline.

type LogList

type LogList struct {
	Kind  string     `json:"kind"`
	Items []LogEntry `json:"items"`
	// TruncatedBefore, when set, is the time the loaded history is cut at:
	// older entries exist on the remote but are not here (a shallow clone).
	TruncatedBefore string `json:"truncatedBefore,omitempty"`
}

LogList is the GET /cards/{uid}/log response envelope.

func CardLogFrom added in v0.26.0

func CardLogFrom(c board.Card, events []board.Event, truncatedBefore time.Time) LogList

CardLogFrom merges the given events — a backend's history — with the card's notes into one chronological feed, naming the horizon the history is cut at when there is one.

type Member added in v0.26.0

type Member struct {
	Login     string `json:"login"`
	Name      string `json:"name,omitempty"`
	AvatarURL string `json:"avatarUrl,omitempty"`
	// Carrying is how much open work is this person's right now, counted
	// across EVERY team — a board is read through a filter and a person is
	// not, so handing somebody a card without the whole number in front of
	// you is a decision made in the dark (board.CarryingNow).
	Carrying int `json:"carrying,omitempty"`
	// Load is the same work WEIGHED — the points of what the person is
	// carrying (board.LoadNow) — and Capacity the points a week they get
	// through: the roster's number, absent when nobody has set one
	// (board.CapacityOfPerson). A day board draws load/capacity beside the
	// person and goes red past it; with no capacity it draws the load alone.
	Load     int `json:"load,omitempty"`
	Capacity int `json:"capacity,omitempty"`
}

Member is one person on the board: a login and, when the server knows the forge, an avatar image URL and — on a forge that has them (GitLab) — a display name. The login is the identity everywhere; the name is for eyes.

func MembersOf added in v0.37.0

func MembersOf(b board.Board, person func(login string) Member) []Member

MembersOf is the board's people with the numbers beside each: everyone who is assigned anything, in login order, with what they are carrying (cards), what it weighs (points) and how many points a week they get through.

It is separate from the board resource because those numbers change on every card write while the rest of the metadata — teams, columns, processes — changes rarely: a watcher can be told the people alone, which is a frame of a couple of kilobytes rather than the whole roster.

type Note

type Note struct {
	Kind     string       `json:"kind"`
	Metadata NoteMetadata `json:"metadata"`
	Spec     NoteSpec     `json:"spec"`
}

Note is a work note as an API resource, a subresource of a card.

func NoteResources

func NoteResources(c board.Card) []Note

NoteResources maps a card's notes onto Note resources.

type NoteMetadata

type NoteMetadata struct {
	ID        string `json:"id"`
	CardUID   string `json:"cardUid"`
	Author    string `json:"author,omitempty"`
	CreatedAt string `json:"createdAt,omitempty"`
	Source    string `json:"source"`
}

type NoteSpec

type NoteSpec struct {
	Text string `json:"text"`
}

type Ordering

type Ordering struct {
	Kind string       `json:"kind"`
	Spec OrderingSpec `json:"spec"`
}

Ordering is the board-level manual order: the uid list clients sort by.

func OrderingResource

func OrderingResource(b board.Board) Ordering

OrderingResource is the board's manual order as a resource.

type OrderingSpec

type OrderingSpec struct {
	UIDs []string `json:"uids"`
}

type PersonalInfo added in v0.26.0

type PersonalInfo struct {
	Domain string `json:"domain"`
	URL    string `json:"url"`
	// Problem says why the linked repository is not attached — the server
	// cannot reach it — and ActionURL is what fixes it (installing the
	// board's GitHub App on the repository). Both empty when the board is
	// attached and well.
	Problem   string `json:"problem,omitempty"`
	ActionURL string `json:"actionUrl,omitempty"`
}

PersonalInfo is the visitor's personal repository as the board knows it: the domain it is served as and the repository it is.

type Process added in v0.18.0

type Process struct {
	Name    string `json:"name"`
	Project string `json:"project,omitempty"`
	Paused  bool   `json:"paused,omitempty"`
	Tasks   []Task `json:"tasks"`
}

Process is one process and the tasks it iterates on.

type ProcessList added in v0.18.0

type ProcessList struct {
	Kind  string    `json:"kind"`
	Items []Process `json:"items"`
}

ProcessList is the Process tab on the wire: every process with its tasks, each task with its recent history — enough to draw the tab and to answer "is this process alive" without a second request.

func ProcessesResource added in v0.18.0

func ProcessesResource(b board.Board, project string) ProcessList

ProcessesResource builds the Process tab from a board, filtered to one project when asked ("" = every project).

type ProcessRef added in v0.18.0

type ProcessRef struct {
	Name    string `json:"name"`
	Project string `json:"project,omitempty"`
}

ProcessRef is one process: its name and project.

type Selector

type Selector struct {
	// View is "", "all", "team", "me", "personal", "triage", "backlog" or "project". "" and "all" both list every
	// card (the HTTP/MCP layer defaults an unspecified view to the caller's "me").
	View string
	// Team is the team key for the team/triage views ("" = the no-team group).
	Team string
	// Day is the viewed day for the team/me views (defaults to today).
	Day string
	// User is the person for the me view ("" = everyone).
	User string
	// From and Weeks bound the triage view: the columns from the Monday
	// From (defaults to the current week) for Weeks weeks (defaults to 6).
	From  string
	Weeks int
	// Project filters the project view to one project's epic columns. Empty
	// means every project — the all-projects overview. Note this is the
	// planning entity, NOT the GitHub board (that is addressed by owner+board).
	Project string
	// RecordCards are the cards this listing is a RECORD of — what the day's
	// board took from that evening, by id (board.MergeAsOf). Only they give
	// back what the × took off (LeftOn): a card of a team still inside that
	// sprint is live, and the × took it off that day on purpose. Set together
	// with LeftOn.
	RecordCards map[string]bool
	// LeftOn gives a day back what the × took off it: a card finished that
	// day and tidied away carries the day it was LEFT on (board.Card.LeftAt)
	// while its dates have moved into the previous sprint, so nothing else
	// remembers where it was worked. Set only when a day is read as a RECORD
	// — today's board must not show it, since taking the card off today is
	// what the × is for (G60).
	LeftOn string
	// Snapshot asks for the board OF the day rather than today's board
	// filtered by it: every card as it stood when that day ended. Only a
	// PAST day has one — today is the live board — and only storage that
	// keeps history can answer (git does).
	Snapshot bool
	// Fields picks the resource shape a listing delivers. The default is the
	// board row — no description, with the derived link refs in status
	// standing in for it; a card's body is one GET /cards/{uid} away.
	// "full" opts a genuine bulk reader into complete Cards.
	Fields string
	// Plain field selectors, applied on top of the view (or of all cards).
	Stage    *string
	Zone     *string
	Assignee string
	// Focus keeps only workable cards — the "what can I act on now" filter
	// (drops done, on-review and locked). It mirrors the Me view's focus toggle.
	Focus bool
	// IncludeReviews brings review cards into a view. On me/team it APPENDS
	// each returned card's linked review, so a client rendering the reviewer
	// badge has it on hand without a second request; on triage it KEEPS the
	// review cards the grid otherwise leaves out, placed by their own dates
	// (board.TriageWeekOf). One flag, one meaning — reviews ride along — and
	// off by default in both: agents listing a Me board do not want them
	// mixed in, and a grid full of open reviews is not a plan.
	IncludeReviews bool
}

Selector scopes a card LIST or watch subscription. View selectors reproduce exactly what the UI renders (the Team grid, the Me day board, the Triage weeks); the plain field selectors compose with no view.

func ParseSelector

func ParseSelector(q url.Values) (Selector, error)

ParseSelector reads a selector from query parameters. Unknown views error.

func (Selector) Matches

func (s Selector) Matches(b board.Board, c board.Card) bool

Matches reports whether a single card is in the selector's scope — the watch hub uses it to compute per-subscription membership deltas. It must agree with FilterCards.

type Sprint

type Sprint struct {
	Kind     string         `json:"kind"`
	Metadata SprintMetadata `json:"metadata"`
	Spec     SprintSpec     `json:"spec"`
}

Sprint is a team's sprint pointer as an API resource (name = the team key, "" is the no-team group).

func SprintResourceOf added in v0.37.0

func SprintResourceOf(b board.Board, team string) Sprint

SprintResourceOf shapes ONE team's sprint resource. The watch frame for a team and the listing go through it together, so a frame cannot carry less than the listing does — which is how a client that merges frames in place came to lose the team's capacity every time a sprint pointer moved.

func SprintResources

func SprintResources(b board.Board) []Sprint

SprintResources maps the board's per-team pointers onto Sprint resources, sorted by team for stable output.

type SprintCapacity added in v0.32.0

type SprintCapacity struct {
	Points int `json:"points,omitempty"`
}

SprintCapacity is a team's capacity as the API states it: the POINTS a week it gets through, a number somebody SET and never derived — absent when nobody has said. The Triage board holds each week's scheduled points against it.

type SprintMetadata

type SprintMetadata struct {
	Team string `json:"team"`
}

type SprintSpec

type SprintSpec struct {
	Current  string `json:"current,omitempty"`
	Previous string `json:"previous,omitempty"`
	// Capacity is what a week of the team's plan is weighed against.
	Capacity *SprintCapacity `json:"capacity,omitempty"`
}

type Task added in v0.18.0

type Task struct {
	UID         string `json:"uid"`
	Title       string `json:"title"`
	Description string `json:"description,omitempty"`
	Recurrence  string `json:"recurrence"`
	Start       string `json:"start,omitempty"`
	Team        string `json:"team,omitempty"`
	Assignee    string `json:"assignee,omitempty"`
	Accumulate  bool   `json:"accumulate,omitempty"`
	// History lists the task's recent turns, oldest first, as they went —
	// the last HistoryShown of them. A process that has run for a year has
	// fifty, nobody reads more than the recent ones, and this list rides in
	// every board frame.
	History []Iteration `json:"history"`
	// Turns, Done and Late count ALL of them, so the tail that is not sent
	// still counts. Turns == len(History) means nothing was left out.
	Turns int `json:"turns"`
	Done  int `json:"done"`
	Late  int `json:"late"`
	// Due is the weeks this task comes due in over the planning horizon and
	// has no turn of its own yet — what the process is going to file. A board
	// that plans weeks ahead has to show it: a week already spoken for by a
	// process is not a week the team is free in. A paused process sends
	// none, because it files none.
	Due []string `json:"due,omitempty"`
}

Task is what an iteration is copied from, plus how the last few went.

Jump to

Keyboard shortcuts

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