knowledge-base.progress takes since: only what changed in a window, read from the tracker's and mesh-delivery's history, so a five-minute report says what moved (the operator, 2026-10-28)

This commit is contained in:
2026-10-28 12:33:01 +01:00
parent 25f6154564
commit 4f317201c9
18 changed files with 758 additions and 8 deletions
@@ -56,6 +56,8 @@ type ProgressAsk struct {
Of string
Detail string
Bound int
// Since is a window, such as 60m: the answer is then only what changed in it (progress_since.go).
Since string
}
// Item is one thing whose progress is said: a design, a milestone, an issue, a pull request.
@@ -81,6 +83,11 @@ type Progress struct {
Source string `json:"source"`
ReadAt time.Time `json:"read-at"`
Cut string `json:"cut,omitempty"`
// Since and Changes are said for an answer about a window: how long it is and how many changes it holds.
Since string `json:"since,omitempty"`
Changes int `json:"changes,omitempty"`
// scope is what the answer is about, kept for a window's answer; nil without since.
scope *sinceScope
}
// trackerRow is a row of `issue-tracker.list`.
@@ -137,9 +144,15 @@ func (k *KB) Progress(a ProgressAsk) (*Progress, error) {
if k.Seats == nil {
return nil, errors.New("the knowledge base reaches no other seat here")
}
window, err := parseSince(a.Since)
if err != nil {
return nil, err
}
of := strings.Join(strings.Fields(a.Of), " ")
p := &Progress{Of: of, Detail: detail, ReadAt: k.now()}
var err error
if window > 0 {
p.scope = &sinceScope{rows: map[int]trackerRow{}}
}
switch {
case strings.EqualFold(of, "mesh"):
err = k.progressMesh(p)
@@ -168,6 +181,9 @@ func (k *KB) Progress(a ProgressAsk) (*Progress, error) {
if err != nil {
return nil, err
}
if window > 0 {
k.progressSince(p, window)
}
// A cut takes the warnings from the last: the calls that failed are said before the answers that did not parse.
callsFirst(p.Warnings)
fitProgress(p, boundOf(a.Bound))
@@ -340,8 +356,9 @@ func (k *KB) progressDesign(p *Progress, number int, milestone string) error {
}
items, warn := milestoneItems(ms, rows, missing)
p.Warnings = append(p.Warnings, warn...)
p.scope.hold(rows, ms)
var extra *extras
if p.Detail == DetailDetailed {
if p.Detail == DetailDetailed && p.scope == nil {
if extra, err = k.readExtras(items); err != nil {
return err
}
@@ -394,6 +411,10 @@ func (k *KB) progressMesh(p *Progress) error {
for _, n := range missingList {
missing[n] = true
}
p.scope.hold(rows, with...)
if p.scope != nil {
p.scope.every = true
}
top := Item{ID: "mesh", Title: "the designs being built"}
var kids []Item
for _, d := range with {
@@ -441,6 +462,11 @@ func (k *KB) progressIssue(p *Progress, n int) error {
}
it.ID = fmt.Sprintf("issue %d", n)
p.Source = "the issue tracker and mesh-delivery"
if p.scope != nil {
p.scope.hold(rows)
p.State, p.Items = it.State, []Item{it}
return nil
}
extra, err := k.readExtras([]Item{{Children: []Item{{ID: strconv.Itoa(n), State: StateMoving}}}})
if err != nil {
return err
@@ -513,6 +539,9 @@ func (k *KB) progressRecord(p *Progress, kind string, n int) error {
p.Warnings = append(p.Warnings, fmt.Sprintf("%d issues are linked to %s; the first %d are counted", l.Matched, name, len(l.Rows)))
}
for _, r := range l.Rows {
if p.scope != nil {
p.scope.rows[r.Number] = r
}
if it, counts := issueItem(r); counts {
kids = append(kids, it)
}