From 3aaccba4e2475da751e42490e4d228301c6bf228 Mon Sep 17 00:00:00 2001 From: jochen Date: Sun, 11 Oct 2026 12:24:45 +0200 Subject: [PATCH] mesh-issues: read merged from the pull request, not the state, so a closed one is withdrawn (hq issue 483) mesh-delivery says stopped for a pull request closed unmerged too; read as merged, it was said stuck to the operator for good. Cite ADR 0284 for the worker rules, which the comments gave as 0283. --- modules/mesh-issues/README.md | 11 ++-- .../mesh-issues/cmd/mesh-issues/bus_test.go | 2 +- modules/mesh-issues/cmd/mesh-issues/claims.go | 11 ++-- .../mesh-issues/cmd/mesh-issues/delivery.go | 59 ++++++++++++++----- modules/mesh-issues/cmd/mesh-issues/groom.go | 2 +- modules/mesh-issues/cmd/mesh-issues/issue.go | 6 +- modules/mesh-issues/cmd/mesh-issues/main.go | 5 +- .../cmd/mesh-issues/memory_test.go | 2 +- modules/mesh-issues/cmd/mesh-issues/ready.go | 2 +- .../mesh-issues/cmd/mesh-issues/tracker.go | 14 ++--- .../cmd/mesh-issues/tracker_test.go | 2 +- .../mesh-issues/cmd/mesh-issues/tracking.go | 5 +- modules/mesh-issues/cmd/mesh-issues/worker.go | 6 +- .../cmd/mesh-issues/worker_test.go | 10 ++-- 14 files changed, 88 insertions(+), 49 deletions(-) diff --git a/modules/mesh-issues/README.md b/modules/mesh-issues/README.md index 7401f1fd..7e2c21e0 100644 --- a/modules/mesh-issues/README.md +++ b/modules/mesh-issues/README.md @@ -30,13 +30,13 @@ what it refuses. | `reserve` | `kind` (`decision` or `research`), optionally `for` (one line: what the record is about) | the next number of that kind, spent forever; answers `kind` and `number` (and `prefix`, the number as the record's name starts with it); see below | **The cycle's rules, at the write** (hq playbook 03, which `00-META/checks/cycle.py` enforced on the -folders until the import, and hq ADR 0283): a status is one of `open`, +folders until the import, and hq ADR 0284): a status is one of `open`, `diagnosing`, `located`, `fixing`, `resolved`, `wontfix`; `diagnosing` and `fixing` need `by`; `located` needs `located-in`; `resolved` is reached only from `fixing` and needs `located-in` and `fixed-by`; a core issue (located in the controller, the node-engine, the tool runner, the SDK, or the catalogue's bus, forge or build agent) resolves with `replay` or `replay-none`; `wontfix` needs a `reason`. A refused change changes nothing and says which rule refused it. -**Who works on it** (hq ADR 0283). A move to `diagnosing` or `fixing` names in `by` the issue's **worker**: who +**Who works on it** (hq ADR 0284). A move to `diagnosing` or `fixing` names in `by` the issue's **worker**: who works on it and its node, as `who@node` (such as `fix-399@g14` or `jochen@shanks`, kept in lower case). The issue keeps its worker (`worker`: `by`, `since`, `active`) while it stays at either status; any other status ends the work. `get` shows it, with `worker-stale`, and each `list` row shows `worker`, `since` and `stale`. A move to either @@ -113,7 +113,10 @@ nothing. **The fixes of an issue are its `fixed-by` and the pull requests linked to it** (link kind `pull-request`; hq issue 483): agents link a pull request while the issue is in fixing and give `fixed-by` at the resolve, so a delivery read on `fixed-by` alone missed every fix being verified. Readiness still reads `fixed-by` alone, so a pull request linked -and abandoned holds no dependent back. A pull request linked after its delivery moved hears no transition again: each +and abandoned holds no dependent back. A pull request closed without merging (`stopped`, and never merged) is **withdrawn**: not +a fix awaiting delivery, not delivered, not open; the line says "fix withdrawn: …" when it is the only one. Merged is +read from the delivery's `merged_as` or the pull request's own `merged`, never from the state, since `stopped` is +also what a closed pull request becomes. A pull request linked after its delivery moved hears no transition again: each sweep asks mesh-delivery for at most five fixes never heard of, of issues not resolved. The ready-to-verify note names each fix with when it was delivered, and the issue's worker; the event carries @@ -282,7 +285,7 @@ said (hq issue 483). - `decision-floor`, `research-floor` — the highest decision and research numbers taken where the tracker cannot read, such as an open branch of hq (293 and 45 when this was written: 0293 on an open branch, 045 on main). Read once, when that kind's counter starts; see *Decision and research numbers*. -- `worker-stale-after` — how long an issue's worker stays current with nothing done on the issue (hq ADR 0283), +- `worker-stale-after` — how long an issue's worker stays current with nothing done on the issue (hq ADR 0284), as a duration; `24h` when empty. - `owners` — the registered list `located-in` may name: repositories, and modules as `mesh-catalog modules/`. An entry of `located-in` is an owner, or an owner followed by a space or a diff --git a/modules/mesh-issues/cmd/mesh-issues/bus_test.go b/modules/mesh-issues/cmd/mesh-issues/bus_test.go index 5ae56806..366b386d 100644 --- a/modules/mesh-issues/cmd/mesh-issues/bus_test.go +++ b/modules/mesh-issues/cmd/mesh-issues/bus_test.go @@ -523,7 +523,7 @@ func TestAnIssueIsOpenedNotedLinkedMovedAndListedOverTheBus(t *testing.T) { var kinds []string for _, e := range events { kinds = append(kinds, e.Key) - // The move to fixing carries who works on it; every other change, who acted (ADR 0283 §4). + // The move to fixing carries who works on it; every other change, who acted (ADR 0284 §6). want := Unproven if e.Key == EventMoved && e.Body["to"] == StatusFixing { want = "fix-365@g14" diff --git a/modules/mesh-issues/cmd/mesh-issues/claims.go b/modules/mesh-issues/cmd/mesh-issues/claims.go index b61294e6..e53427f2 100644 --- a/modules/mesh-issues/cmd/mesh-issues/claims.go +++ b/modules/mesh-issues/cmd/mesh-issues/claims.go @@ -56,7 +56,7 @@ func deliveredNotResolved(is *Issue) bool { return is.Status == StatusFixing && // deliveredAt is when the last of an issue's delivered fixes was delivered, as the delivery said it. func deliveredAt(is *Issue) time.Time { var last time.Time - for _, pr := range fixPullRequests(is) { + for _, pr := range liveFixes(is) { if f := fixOf(is, pr); f != nil && contains(is.Delivered, pr) && f.Since.After(last) { last = f.Since } @@ -81,7 +81,7 @@ func (t *Tracker) sayNotResolved(is *Issue, now time.Time) (bool, error) { worker = is.Worker.By } ago := now.Sub(at).Round(time.Minute) - prs := strings.Join(fixPullRequests(is), ", ") + prs := strings.Join(liveFixes(is), ", ") if err := t.Notify(notResolvedKey(is.Number), "warning", fmt.Sprintf("issue %d: fixed and delivered, not resolved; %s works on it", is.Number, worker), fmt.Sprintf("Fixed and delivered, not resolved (issue %d)", is.Number), @@ -145,7 +145,7 @@ func (t *Tracker) askUnheard() error { if since.IsZero() { since = t.now() } - if _, err := t.recordFix(pr, d.State, d.Why, afterMerge(d.State), since, n); err != nil { + if _, err := t.recordFix(pr, d.State, d.Why, d.Merged, since, n); err != nil { return err } heard = true @@ -160,9 +160,10 @@ func (t *Tracker) askUnheard() error { } // openPullRequest says whether an issue names a pull request not merged yet, or one whose delivery the tracker -// never heard of: work in review is work, and a fix unheard of is not taken for none. +// never heard of: work in review is work, and a fix unheard of is not taken for none. One closed without merging +// is not open. func openPullRequest(is *Issue) bool { - for _, pr := range fixPullRequests(is) { + for _, pr := range liveFixes(is) { f := fixOf(is, pr) if f == nil || (!f.Merged && !contains(is.Delivered, pr)) { return true diff --git a/modules/mesh-issues/cmd/mesh-issues/delivery.go b/modules/mesh-issues/cmd/mesh-issues/delivery.go index 749c8c57..d56c73f0 100644 --- a/modules/mesh-issues/cmd/mesh-issues/delivery.go +++ b/modules/mesh-issues/cmd/mesh-issues/delivery.go @@ -44,13 +44,36 @@ func reached(state string) bool { return state == "delivered" || state == "covered" || state == "retired" } -// afterMerge says whether a state is one a delivery reaches only once merged. -func afterMerge(state string) bool { - switch state { - case "published", "delivering", "held", "delivered", "failed", "stopped", "covered", "retired": - return true +// Whether a pull request is merged is what the delivery says of the pull request itself — `merged_as` on a +// transition, the pull request's `merged` in checks — never read from the state: `stopped` is also what a pull +// request closed without merging becomes (mesh-delivery's `closed` event), and read as merged it was said stuck to +// the operator for good (novox/hq issue 483). + +// withdrawn says whether a fix is a pull request closed without merging: no fix at all, neither awaiting delivery, +// delivered, nor open. +func withdrawn(f *Fix) bool { return f != nil && f.State == "stopped" && !f.Merged } + +// liveFixes is an issue's fixes less those withdrawn: what its delivery, readiness to verify, the stuck sweep and a +// stale claim are measured on. fixPullRequests still names the withdrawn ones, so a pull request reopened is heard. +func liveFixes(is *Issue) []string { + var out []string + for _, pr := range fixPullRequests(is) { + if !withdrawn(fixOf(is, pr)) { + out = append(out, pr) + } } - return false + return out +} + +// withdrawnFixes is the pull requests of an issue closed without merging. +func withdrawnFixes(is *Issue) []string { + var out []string + for _, pr := range fixPullRequests(is) { + if withdrawn(fixOf(is, pr)) { + out = append(out, pr) + } + } + return out } func fixOf(is *Issue, pr string) *Fix { @@ -64,7 +87,7 @@ func fixOf(is *Issue, pr string) *Fix { // allDelivered says whether an issue names a pull request and every one is delivered. func allDelivered(is *Issue) bool { - prs := fixPullRequests(is) + prs := liveFixes(is) if len(prs) == 0 { return false } @@ -79,8 +102,11 @@ func allDelivered(is *Issue) bool { // DeliveryLine is the derived delivery state of an issue's fix, in words; empty when fixed-by names no pull // request. func DeliveryLine(is *Issue) string { - prs := fixPullRequests(is) + prs := liveFixes(is) if len(prs) == 0 { + if w := withdrawnFixes(is); len(w) > 0 { + return "fix withdrawn: " + strings.Join(w, ", ") + " closed without merging" + } return "" } var held, failed, merged, open, unheard []string @@ -182,7 +208,7 @@ func (t *Tracker) afterFix(n uint64) error { } if allDelivered(is) { if unresolved(is) { - prs := fixPullRequests(is) + prs := liveFixes(is) sort.Strings(prs) if strings.Join(is.VerifyFor, ",") != strings.Join(prs, ",") { // The note first, kept once by its words; then the claim; then the event. A failure before the claim @@ -245,7 +271,7 @@ func stillStuck(is *Issue) bool { if is.Status == StatusWontfix { return false } - named := fixPullRequests(is) + named := liveFixes(is) for _, f := range is.Fixes { if f.StuckSaid && contains(named, f.PullRequest) && !contains(is.Delivered, f.PullRequest) { return true @@ -296,7 +322,7 @@ func (t *Tracker) OnTransition(e stdio.Envelope) error { if at.IsZero() { at = t.now() } - merged := body.MergedAs != "" || afterMerge(body.To) + merged := body.MergedAs != "" changed, err := t.recordFix(prKey(body.Repository, body.Number), body.To, body.Why, merged, at, 0) if err != nil { return err @@ -315,6 +341,8 @@ type Delivery struct { Why string // Since is when the delivery entered its state, as it says; zero when it does not. Since time.Time + // Merged is the pull request's own merged flag, as the forge says it. + Merged bool } // DeliveryState asks mesh-delivery for one pull request's delivery. @@ -333,11 +361,14 @@ func busDeliveryState(owner string) DeliveryState { Waits string `json:"waits"` Since time.Time `json:"since"` } `json:"delivery"` + Pull struct { + Merged bool `json:"merged"` + } `json:"pull"` } if err := json.Unmarshal(raw, &out); err != nil { return Delivery{}, fmt.Errorf("mesh-delivery's checks answered no delivery: %.200s", raw) } - return Delivery{State: out.Delivery.State, Why: out.Delivery.Waits, Since: out.Delivery.Since.UTC()}, nil + return Delivery{State: out.Delivery.State, Why: out.Delivery.Waits, Since: out.Delivery.Since.UTC(), Merged: out.Pull.Merged}, nil } } @@ -386,7 +417,7 @@ func (t *Tracker) OnMoved(e stdio.Envelope) error { if since.IsZero() { since = t.now() } - if _, err := t.recordFix(pr, state, d.Why, afterMerge(state), since, body.Number); err != nil { + if _, err := t.recordFix(pr, state, d.Why, d.Merged, since, body.Number); err != nil { return err } } @@ -452,7 +483,7 @@ func (t *Tracker) Sweep() (int, error) { if err := t.clearStuck(is); err != nil { t.Logf("[mesh-issues] the stuck fix of %d could not be cleared on the operator's channel: %v", n, err) } - named := fixPullRequests(is) + named := liveFixes(is) for _, f := range is.Fixes { if !contains(named, f.PullRequest) || contains(is.Delivered, f.PullRequest) || !f.Merged || f.MergedAt == nil || reached(f.State) || f.StuckSaid || now.Sub(*f.MergedAt) < bound { diff --git a/modules/mesh-issues/cmd/mesh-issues/groom.go b/modules/mesh-issues/cmd/mesh-issues/groom.go index 88b00a0d..bf2b2877 100644 --- a/modules/mesh-issues/cmd/mesh-issues/groom.go +++ b/modules/mesh-issues/cmd/mesh-issues/groom.go @@ -125,7 +125,7 @@ type Verdict struct { func (v Verdict) closes() bool { return v.Verdict == VerdictDuplicate && v.Certain } // unresolved says whether an issue may be offered, linked or noted by the triage: at open, diagnosing, located or -// fixing (ADR 0283 §5). +// fixing (ADR 0284 §7). func unresolved(is *Issue) bool { return is.Status == StatusOpen || is.Status == StatusDiagnosing || is.Status == StatusLocated || is.Status == StatusFixing } diff --git a/modules/mesh-issues/cmd/mesh-issues/issue.go b/modules/mesh-issues/cmd/mesh-issues/issue.go index 351625c0..4a9e8b01 100644 --- a/modules/mesh-issues/cmd/mesh-issues/issue.go +++ b/modules/mesh-issues/cmd/mesh-issues/issue.go @@ -21,9 +21,9 @@ const ( IssueCounter = "issue" ) -// The six statuses of an issue, as the development cycle names them (hq playbook 03, ADR 0275, ADR 0283). +// The six statuses of an issue, as the development cycle names them (hq playbook 03, ADR 0275, ADR 0284). // Fixing is the status an agent or person moves an issue to when they start its fix; resolved is reached -// only from it (ADR 0283 §3). +// only from it (ADR 0284 §5). const ( StatusOpen = "open" StatusDiagnosing = "diagnosing" @@ -110,7 +110,7 @@ type Issue struct { ReadyFor []uint64 `json:"ready-for,omitempty"` // Triage is the triage's judgement as it was made, kept before it is applied. Triage *Verdict `json:"triage,omitempty"` - // Worker is who works on it, while it is diagnosing or fixing (ADR 0283); nil at every other status. + // Worker is who works on it, while it is diagnosing or fixing (ADR 0284); nil at every other status. Worker *Worker `json:"worker,omitempty"` // Opening is the id of the call that opened it, so a write whose answer was lost is known as its own. Opening string `json:"opening"` diff --git a/modules/mesh-issues/cmd/mesh-issues/main.go b/modules/mesh-issues/cmd/mesh-issues/main.go index 7e9d5bf2..c5e7e8e1 100644 --- a/modules/mesh-issues/cmd/mesh-issues/main.go +++ b/modules/mesh-issues/cmd/mesh-issues/main.go @@ -44,7 +44,7 @@ type Settings struct { // StuckAfter is how long a fix may be merged and not delivered before it is said stuck (ADR 0281), as a // duration such as 2h; DefaultStuckAfter when empty. StuckAfter string `json:"stuck-after,omitempty"` - // WorkerStaleAfter is how long an issue's worker stays current with nothing done on it (ADR 0283 §2), as a + // WorkerStaleAfter is how long an issue's worker stays current with nothing done on it (ADR 0284 §4), as a // duration such as 24h; DefaultWorkerStaleAfter when empty. WorkerStaleAfter string `json:"worker-stale-after,omitempty"` // DeliveredNotResolvedAfter is how long an issue may stay in fixing once every fix it names is delivered before @@ -626,7 +626,8 @@ func Tools(t *Tracker) []stdio.Tool { Description: "Which issues track which conditions: for every condition key an issue links (link kind condition), " + "or only the keys given, the issues that link it, those not closed (resolved or wontfix) first, each with its status, " + "severity, what it needs, who works on it since when and whether they went quiet (stale), and where its " + - "fix is (fix: not-merged, merged, held, failed, unheard or delivered; empty when none is named). The " + + "fix is (fix: not-merged, merged, held, failed, unheard, delivered, or withdrawn when every pull request named was " + + "closed without merging; empty when none is named). The " + "operator's channel asks it to say in a condition's message which issue tracks it. Refused: a key not of a condition " + "key's shape.", Input: schema(nil, map[string]any{ diff --git a/modules/mesh-issues/cmd/mesh-issues/memory_test.go b/modules/mesh-issues/cmd/mesh-issues/memory_test.go index 523f90ff..f0d663ad 100644 --- a/modules/mesh-issues/cmd/mesh-issues/memory_test.go +++ b/modules/mesh-issues/cmd/mesh-issues/memory_test.go @@ -203,7 +203,7 @@ func (h *harness) open(t *testing.T, title string, located ...string) uint64 { return o.Number } -// fixing moves an issue to fixing, as the agent that starts its fix does (ADR 0283). +// fixing moves an issue to fixing, as the agent that starts its fix does (ADR 0284). func (h *harness) fixing(t *testing.T, n uint64) { t.Helper() if _, err := h.Move(MoveAsk{Number: n, Status: StatusFixing, By: "fix@g14"}); err != nil { diff --git a/modules/mesh-issues/cmd/mesh-issues/ready.go b/modules/mesh-issues/cmd/mesh-issues/ready.go index a6a5f3c7..2a0ff76b 100644 --- a/modules/mesh-issues/cmd/mesh-issues/ready.go +++ b/modules/mesh-issues/cmd/mesh-issues/ready.go @@ -289,7 +289,7 @@ type View struct { Ready bool `json:"ready"` // Delivery is whether its fix is delivered, in words (ADR 0281). Delivery string `json:"delivery,omitempty"` - // WorkerStale says nothing was done on it by its worker, or anyone, for worker-stale-after (ADR 0283 §2). + // WorkerStale says nothing was done on it by its worker, or anyone, for worker-stale-after (ADR 0284 §4). WorkerStale bool `json:"worker-stale,omitempty"` // DeliveredNotResolved and StaleClaim are list's flags, said of this issue (novox/hq issue 483). DeliveredNotResolved bool `json:"delivered-not-resolved,omitempty"` diff --git a/modules/mesh-issues/cmd/mesh-issues/tracker.go b/modules/mesh-issues/cmd/mesh-issues/tracker.go index 3d4c899d..4720652c 100644 --- a/modules/mesh-issues/cmd/mesh-issues/tracker.go +++ b/modules/mesh-issues/cmd/mesh-issues/tracker.go @@ -330,9 +330,9 @@ type MoveAsk struct { Replay string ReplayNone string Reason string - // By is who works on it, who@node: what a move to diagnosing or fixing needs (ADR 0283 §1). + // By is who works on it, who@node: what a move to diagnosing or fixing needs (ADR 0284 §2). By string - // TakeOver is why the issue is taken over from another worker (ADR 0283 §1). + // TakeOver is why the issue is taken over from another worker (ADR 0284 §3). TakeOver string } @@ -422,7 +422,7 @@ func (t *Tracker) move(by string, a MoveAsk) (*Moved, error) { if reason != "" && to != StatusWontfix { return nil, fmt.Errorf("reason is what wontfix needs; this moves to %s", to) } - // Who works on it (ADR 0283 §1): named on a move to diagnosing or fixing, and on no other. + // Who works on it (ADR 0284 §2): named on a move to diagnosing or fixing, and on no other. var worker, takeOver string if worked(to) { if strings.TrimSpace(a.By) == "" { @@ -507,7 +507,7 @@ func (t *Tracker) move(by string, a MoveAsk) (*Moved, error) { out := &Moved{Number: is.Number, From: from, To: to, Changed: changed, By: by, TookOverFrom: work.from, Released: work.released, Said: fmt.Sprintf("Issue %d moved from %s to %s.", is.Number, from, to)} // The event's by is who works on it when the move names them, and who acted otherwise; caller is always who - // acted, as the runtime proves it (ADR 0283 §4). + // acted, as the runtime proves it (ADR 0284 §6). body := map[string]any{"number": is.Number, "from": from, "to": to, "by": by, "caller": by, "at": t.now()} if is.Worker != nil { since := is.Worker.Since @@ -553,7 +553,7 @@ func (t *Tracker) move(by string, a MoveAsk) (*Moved, error) { } // cycleRules is what the development cycle asks of an issue moving from one status to another (playbook 03, -// to-be 53 §5, ADR 0283), said as the rule that refused it. +// to-be 53 §5, ADR 0284), said as the rule that refused it. func cycleRules(is *Issue, from, to string) error { switch to { case StatusLocated: @@ -562,7 +562,7 @@ func cycleRules(is *Issue, from, to string) error { "(a repository, or \"mesh-catalog modules/\")", is.Number) } case StatusResolved: - // Resolved only from fixing: whoever fixed it said so when they started (ADR 0283 §3). A resolved issue + // Resolved only from fixing: whoever fixed it said so when they started (ADR 0284 §5). A resolved issue // may still have what it holds corrected. if from != StatusFixing && from != StatusResolved { return fmt.Errorf("issue %d is %s, and an issue is resolved only from fixing: move it to fixing with by, "+ @@ -740,7 +740,7 @@ type Row struct { // Delivery is whether its fix is delivered, in words (ADR 0281); empty when fixed-by names no pull request. Delivery string `json:"delivery,omitempty"` // Worker is who works on it and Since since when, while it is diagnosing or fixing; Stale says nobody did - // anything on it for worker-stale-after, so it may be taken over without a reason (ADR 0283). + // anything on it for worker-stale-after, so it may be taken over without a reason (ADR 0284 §4). Worker string `json:"worker,omitempty"` Since *time.Time `json:"since,omitempty"` Stale bool `json:"stale,omitempty"` diff --git a/modules/mesh-issues/cmd/mesh-issues/tracker_test.go b/modules/mesh-issues/cmd/mesh-issues/tracker_test.go index 1308826b..557951d5 100644 --- a/modules/mesh-issues/cmd/mesh-issues/tracker_test.go +++ b/modules/mesh-issues/cmd/mesh-issues/tracker_test.go @@ -259,7 +259,7 @@ func TestAnIssueWithAFolderIsNumberedTitledAndPointsAtItsFolder(t *testing.T) { } } -// The cycle's rules at the write (to-be 53 §5, ADR 0283): one case per row, each refused case changing nothing. +// The cycle's rules at the write (to-be 53 §5, ADR 0284): one case per row, each refused case changing nothing. // A case starts from open, or, with from, from that status reached first (fixing by fix@g14). func TestTheCyclesRulesHoldAtTheWrite(t *testing.T) { const fx = StatusFixing diff --git a/modules/mesh-issues/cmd/mesh-issues/tracking.go b/modules/mesh-issues/cmd/mesh-issues/tracking.go index 64d1344d..28418332 100644 --- a/modules/mesh-issues/cmd/mesh-issues/tracking.go +++ b/modules/mesh-issues/cmd/mesh-issues/tracking.go @@ -43,8 +43,11 @@ type Tracked struct { // when fixed-by names no pull request; failed, held, merged (not delivered yet), not-merged, unheard (nothing // heard from the delivery), or delivered (every pull request it names). func FixState(is *Issue) string { - prs := fixPullRequests(is) + prs := liveFixes(is) if len(prs) == 0 { + if len(withdrawnFixes(is)) > 0 { + return "withdrawn" + } return "" } var failed, held, merged, open, unheard bool diff --git a/modules/mesh-issues/cmd/mesh-issues/worker.go b/modules/mesh-issues/cmd/mesh-issues/worker.go index 1faf2c55..61d58cbb 100644 --- a/modules/mesh-issues/cmd/mesh-issues/worker.go +++ b/modules/mesh-issues/cmd/mesh-issues/worker.go @@ -1,6 +1,6 @@ package main -// Who works on an issue (novox/hq ADR 0283). A move to diagnosing or fixing names, in `by`, the issue's worker: +// Who works on an issue (novox/hq ADR 0284). A move to diagnosing or fixing names, in `by`, the issue's worker: // the agent or person and its node, as who@node. The issue keeps its worker while it stays at either status, and // `get` and `list` show it with since. A move to either by someone else while the worker is not stale is refused, // naming the worker; a take-over gives a reason, and the reason is noted. A worker with no move, note, link or set @@ -95,7 +95,7 @@ type workOutcome struct { released string // the worker whose work ended, on a move to a status that has none } -// workerFor applies a move's worker to an issue, under ADR 0283 §1 and §2: another worker not stale is refused +// workerFor applies a move's worker to an issue, under ADR 0284 §3 and §4: another worker not stale is refused // without a take-over reason; a take-over reason with no other worker to take over from is refused. func workerFor(is *Issue, to, by, takeOver string, now time.Time, staleAfter time.Duration) (workOutcome, error) { var out workOutcome @@ -148,5 +148,5 @@ func takeOverNote(o workOutcome, by, reason string, prev *Worker) string { if reason != "" { s += ". Why: " + reason } - return s + ". (novox/hq ADR 0283)" + return s + ". (novox/hq ADR 0284)" } diff --git a/modules/mesh-issues/cmd/mesh-issues/worker_test.go b/modules/mesh-issues/cmd/mesh-issues/worker_test.go index be814aea..c1e58bbc 100644 --- a/modules/mesh-issues/cmd/mesh-issues/worker_test.go +++ b/modules/mesh-issues/cmd/mesh-issues/worker_test.go @@ -15,7 +15,7 @@ func clocked(h *harness) *time.Time { } // A move to diagnosing or fixing by someone else while the worker is current is refused, naming the worker, and -// changes nothing (ADR 0283 §1). +// changes nothing (ADR 0284 §3). func TestAnotherWorkerIsRefusedNamingTheWorker(t *testing.T) { for _, to := range []string{StatusDiagnosing, StatusFixing} { t.Run(to, func(t *testing.T) { @@ -76,7 +76,7 @@ func TestTheWorkerMovesOn(t *testing.T) { } } -// A take-over gives a reason, the reason is noted, and the moved event says from whom (ADR 0283 §1, §4). +// A take-over gives a reason, the reason is noted, and the moved event says from whom (ADR 0284 §3, §6). func TestATakeOverNeedsAReasonAndIsNoted(t *testing.T) { h := newHarness(t) clocked(h) @@ -103,7 +103,7 @@ func TestATakeOverNeedsAReasonAndIsNoted(t *testing.T) { } // A worker with nothing done on it past worker-stale-after is stale: list and get say so, and it may be taken over -// without a reason, noted (ADR 0283 §2). A caller's note keeps it live; the tracker's own does not. +// without a reason, noted (ADR 0284 §4). A caller's note keeps it live; the tracker's own does not. func TestAStaleWorkerIsShownAndMayBeTakenOverWithoutAReason(t *testing.T) { h := newHarness(t) now := clocked(h) @@ -193,7 +193,7 @@ func TestAMoveOnEndsTheWork(t *testing.T) { } } -// The duplicate check and the triage treat fixing as not closed, like diagnosing and located (ADR 0283 §5). +// The duplicate check and the triage treat fixing as not closed, like diagnosing and located (ADR 0284 §7). func TestFixingIsNotClosed(t *testing.T) { for _, s := range Statuses { want := s != StatusResolved && s != StatusWontfix @@ -261,7 +261,7 @@ func TestAResolvedIssueMayBeCorrected(t *testing.T) { } } -// A caller's link and set keep the worker current, as a note does (ADR 0283 §4). +// A caller's link and set keep the worker current, as a note does (ADR 0284 §4). func TestALinkAndASetKeepTheWorkerCurrent(t *testing.T) { for _, act := range []string{"link", "unlink", "set"} { t.Run(act, func(t *testing.T) {