From 0fafd638442c7d3b518102f637445e3b2b8f0442 Mon Sep 17 00:00:00 2001 From: jochen Date: Sun, 11 Oct 2026 12:26:56 +0200 Subject: [PATCH] Propose ADR 0294: an issue's linked pull requests are its fixes, and a delivered fix left in fixing is loud (issue 483) The tracker measured fixed-by alone while agents link the pull request, so 13 delivered fixes sat unseen in fixing. --- 00-META/glossary.md | 5 + ...and-a-fix-stuck-after-its-merge-is-loud.md | 6 + ...-fix-delivered-and-not-resolved-is-loud.md | 124 ++++++++++++++++++ 3 files changed, 135 insertions(+) create mode 100644 02-DECISIONS/0294-an-issues-fixes-are-its-fixed-by-and-its-linked-pull-requests-and-a-fix-delivered-and-not-resolved-is-loud.md diff --git a/00-META/glossary.md b/00-META/glossary.md index d2ed9f0d..9c9580a6 100644 --- a/00-META/glossary.md +++ b/00-META/glossary.md @@ -606,6 +606,11 @@ Not a domain of the mesh but of the way it is built, listed because its words me worker with nothing done on the issue for a day is **stale**. **Fixing** is the status an issue is at while its fix is worked on; an issue is resolved only from it ([ADR 0284](../02-DECISIONS/0284-an-agent-moves-an-issue-to-fixing-under-its-own-name-and-an-issue-is-resolved-only-from-fixing.md)). Not a *claim* or a *holder*, which are a module's on a seat. +- **abandoned** — of an issue: at `diagnosing` or `fixing`, its worker stale and no pull request of it open; another + worker takes it over without a reason ([ADR 0294](../02-DECISIONS/0294-an-issues-fixes-are-its-fixed-by-and-its-linked-pull-requests-and-a-fix-delivered-and-not-resolved-is-loud.md)). + Not a *stale claim*: a claim is a module's on a seat. +- **fix** — of an issue: a pull request its `fixed-by` names or it links; one closed without merging is + **withdrawn**. An issue at `fixing` with every fix delivered is **delivered, not resolved** ([ADR 0294](../02-DECISIONS/0294-an-issues-fixes-are-its-fixed-by-and-its-linked-pull-requests-and-a-fix-delivered-and-not-resolved-is-loud.md)). - **tracks** — of an issue and a condition: the issue links the condition's key with a link of kind `condition`. The **tracking line** is the line the router says in every message about a condition: the issues that track it and where each stands, or that none does ([ADR 0285](../02-DECISIONS/0285-an-issue-tracks-a-condition-by-its-key-and-every-message-about-the-condition-says-the-issue-and-where-it-stands.md)). diff --git a/02-DECISIONS/0281-an-issue-knows-whether-its-fix-is-delivered-and-a-fix-stuck-after-its-merge-is-loud.md b/02-DECISIONS/0281-an-issue-knows-whether-its-fix-is-delivered-and-a-fix-stuck-after-its-merge-is-loud.md index fbe61fd4..e7ed43de 100644 --- a/02-DECISIONS/0281-an-issue-knows-whether-its-fix-is-delivered-and-a-fix-stuck-after-its-merge-is-loud.md +++ b/02-DECISIONS/0281-an-issue-knows-whether-its-fix-is-delivered-and-a-fix-stuck-after-its-merge-is-loud.md @@ -9,6 +9,12 @@ extends: 02-DECISIONS/0279-the-issue-tracker-triages-every-new-issue-and-an-issu # 281. An issue knows whether its fix is delivered, and a fix stuck after its merge is loud +> **Superseded in part — 2026-10-11, by [ADR 0294](0294-an-issues-fixes-are-its-fixed-by-and-its-linked-pull-requests-and-a-fix-delivered-and-not-resolved-is-loud.md).** +> No longer holds: an issue's fixes are only the pull requests its `fixed-by` names (§1, §2); they are its +> `fixed-by` and its linked pull requests, merged is read from the pull request and not the state, and a fix closed +> unmerged is withdrawn. What stands: the measurement, the delivery line's wording, delivered is not resolved, the +> stuck fix, and readiness on `fixed-by`. + ## Context [ADR 0279](0279-the-issue-tracker-triages-every-new-issue-and-an-issue-is-ready-when-what-it-depends-on-is-delivered.md) diff --git a/02-DECISIONS/0294-an-issues-fixes-are-its-fixed-by-and-its-linked-pull-requests-and-a-fix-delivered-and-not-resolved-is-loud.md b/02-DECISIONS/0294-an-issues-fixes-are-its-fixed-by-and-its-linked-pull-requests-and-a-fix-delivered-and-not-resolved-is-loud.md new file mode 100644 index 00000000..9211bc7c --- /dev/null +++ b/02-DECISIONS/0294-an-issues-fixes-are-its-fixed-by-and-its-linked-pull-requests-and-a-fix-delivered-and-not-resolved-is-loud.md @@ -0,0 +1,124 @@ +--- +topic: how we work +status: proposed +date: 2026-10-11 +deciders: jochen (proposed by the agent session that fixed issue 483; waits for the operator) +reconstructed: false +extends: 02-DECISIONS/0284-an-agent-moves-an-issue-to-fixing-under-its-own-name-and-an-issue-is-resolved-only-from-fixing.md +supersedes-in-part: + - 02-DECISIONS/0281-an-issue-knows-whether-its-fix-is-delivered-and-a-fix-stuck-after-its-merge-is-loud.md +--- + +# 294. An issue's fixes are its fixed-by and its linked pull requests, and a fix delivered and not resolved is loud + +## Context + +[ADR 0281](0281-an-issue-knows-whether-its-fix-is-delivered-and-a-fix-stuck-after-its-merge-is-loud.md) made the +issue tracker measure the delivery of every pull request an issue's `fixed-by` names, and say "ready to verify" when +all are delivered. [ADR 0284](0284-an-agent-moves-an-issue-to-fixing-under-its-own-name-and-an-issue-is-resolved-only-from-fixing.md) +gave an issue a worker, stale after a day with nothing done on it. Issue 483 records what the two left open, +measured on 2026-10-11: + +- **The fix is linked, not named.** The operator found 23 issues in `fixing`; 13 had their fix merged and delivered + hours before. Agents link a pull request to the issue (link kind `pull-request`) while it is in `fixing`, and give + `fixed-by` only when they resolve it. The tracker measured `fixed-by` alone, so it never measured those 13, and + their `delivery` line was empty. +- **Nothing says an issue left in fixing.** Only an instruction asks a session to move an issue into `fixing`; + nothing asks it to move it out, and nothing tells the operator when it does not. +- **A gone worker looks like a working one.** Two issues were held by builders that had stopped hours before. A + stale worker is shown as `stale`, but a worker with a pull request in review is stale by the same rule after a day + of review, so `stale` alone does not tell a forgotten issue from one waiting for a review. +- **A closed pull request is not merged.** mesh-delivery gives a pull request closed without merging the state + `stopped`, the state a delivery stopped after its merge also has. Read from the state, a closed pull request + counts as merged, and after two hours the tracker would tell the operator, for good, that a fix "merged" and was + never delivered. + +## Considered Options + +1. **Ask agents to give `fixed-by` at once.** Rejected: an instruction asked agents to move issues into `fixing` + and the 13 issues show what an instruction alone holds. The tracker already holds the links. +2. **Move an issue to `resolved` when its fixes are delivered.** Rejected: delivered is not resolved (ADR 0281 §3); + the acceptance is proven live first. +3. **Make the warning a controller condition through a health tool.** Rejected for now: the tracker runs only its + bundle, which cannot raise a controller condition (ADR 0240 rule 8, ADR 0256). The operator's channel already + carries the tracker's stuck-fix warning, cleared the same way. +4. **Read the links and the delivery as below.** Chosen. + +## Decision + +### 1. An issue's fixes are its fixed-by and its linked pull requests + +The pull requests an issue's `fixed-by` names and those it links with kind `pull-request` are its **fixes**. The +delivery line, the ready-to-verify note, the stuck fix of ADR 0281 §4 and `tracking`'s `fix` are measured on them. +Readiness (ADR 0279 §3) still reads `fixed-by` alone: a resolved issue's `fixed-by` is what fixed it, and a pull +request linked and abandoned must not hold its dependents back. + +This replaces ADR 0281 §1's "for each pull request an issue's `fixed-by` names" and §2's list over those. + +### 2. Merged is the pull request's own word, and a closed one is withdrawn + +Whether a fix is merged is read from the delivery's `merged_as` or the pull request's own `merged` flag, never from +the delivery's state. A fix `stopped` and never merged is **withdrawn**: not a fix waiting for delivery, not +delivered, and not open. The delivery line says "fix withdrawn: …" when every fix is withdrawn. + +### 3. A fix never heard of is asked at the sweep too + +Besides the asks at the tracker's own `moved` (ADR 0281 §1, at most three per handling), every five-minute sweep +asks mesh-delivery's `checks` for at most five fixes it never heard of, of issues not resolved. A pull request linked +after its delivery moved hears no transition again; without this it would never be measured. + +### 4. The ready-to-verify note names when and who + +The note names each fix with when it was delivered, and the issue's worker; the event `ready-to-verify` carries +`worker` and `delivered-at`. No channel of the tracker reaches a worker, so the note and the event are how it hears. + +### 5. Delivered, not resolved, is loud + +An issue at `fixing` whose every fix is delivered is **delivered, not resolved**. When it has stayed so past the +setting `delivered-not-resolved-after` (**one hour** by default) after its last fix was delivered, the tracker says +it once as a warning on the operator's channel, key `issue-tracker.delivered-not-resolved.`, naming the issue +and its worker. The warning clears when the issue leaves `fixing` or names a fix not yet delivered. One hour is +more than proving an acceptance live takes, and short enough that a worker who left is noticed the same day. + +### 6. An abandoned issue is shown, and taken over without a reason + +An issue at `diagnosing` or `fixing` whose worker is stale (ADR 0284 §4) and that has no pull request open (not +merged and not withdrawn, or never heard of) is **abandoned**. `get` and its `list` row say `abandoned`. A move by +another worker takes it over without a reason, as ADR 0284 §4 already allows of any stale worker; the answer, the +take-over note and the `moved` event say it was abandoned. + +### 7. list filters on both + +`list` takes `flag`: `delivered-not-resolved` or `abandoned`, so the operator sees what is truly being worked on. + +## Consequences + +- An issue that links a pull request now has a delivery line and a ready-to-verify note while it is in `fixing`. + On the first sweeps after this is delivered, the tracker measures the linked pull requests of every issue not + resolved, five per sweep, and warns the operator once for each issue delivered and not resolved past the hour. +- A pull request linked by mistake shows on the delivery line until it is unlinked (`link` with `remove`). +- A fix recorded as merged from the state `stopped` before this decision stays recorded so; it is corrected only + when the delivery says something new of it. +- The word *claim* stays a module's on a seat (the glossary): the issue's own word "stale claim" is said here as + **abandoned**. + +## How it is checked + +| Rule | Checked by | +|---|---| +| A linked pull request is measured and noted once with its time and worker | mesh-issues' test `TestALinkedFixDeliveredIsNotedOnceNamingItsWorker` | +| Delivered, not resolved, is said past the bound, once, cleared when the issue leaves fixing; the bound is the setting | `TestDeliveredNotResolvedIsWarnedAfterTheBoundAndClearedWhenItLeavesFixing`, `TestDeliveredNotResolvedIsRetriedAndClearedAtTheSweep` | +| One pull request linked to several issues is warned and cleared on each | `TestOnePullRequestLinkedToSeveralIssues` | +| A pull request closed unmerged is withdrawn: not merged, not stuck, not delivered, not open | `TestAPullRequestClosedUnmergedIsWithdrawn`, through a transition and through `checks` | +| An abandoned issue is flagged and taken over without a reason | `TestAnAbandonedIssueIsFlaggedAndTakenOverWithoutAReason` | +| The sweep asks a fix never heard of | `TestTheSweepAsksALinkedPullRequestNeverHeardOf` | +| Live | after delivery, `issue-tracker.list` with `flag` `delivered-not-resolved` lists the issues in fixing whose linked fixes were delivered, and the operator's channel says each past the hour | + +## References + +- Issue 483 (an issue whose fix is delivered stays in fixing, and a claim nobody works on is never noticed). +- mesh-catalog pull request 212 (modules/mesh-issues). +- [ADR 0281](0281-an-issue-knows-whether-its-fix-is-delivered-and-a-fix-stuck-after-its-merge-is-loud.md), + [ADR 0284](0284-an-agent-moves-an-issue-to-fixing-under-its-own-name-and-an-issue-is-resolved-only-from-fixing.md), + [ADR 0240](0240-a-module-says-how-it-is-healthy-and-the-node-engine-judges-it.md), + [ADR 0256](0256-a-machines-hardware-condition-is-read-by-one-module-on-every-machine-and-a-fault-is-said-through-its-health.md).