Propose ADR 0294: an issue's linked pull requests are its fixes, and a delivered fix left in fixing is loud (issue 483)
mesh/merge-gate pass: the change touches no module of the mesh's graph
mesh/repo-check pass: its merge-check.sh passed
mesh/delivery superseded: a newer head of the same pull request

The tracker measured fixed-by alone while agents link the pull request,
so 13 delivered fixes sat unseen in fixing.
This commit is contained in:
2026-10-11 12:26:56 +02:00
parent f08920199d
commit 0fafd63844
3 changed files with 135 additions and 0 deletions
+5
View File
@@ -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)).
@@ -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)
@@ -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.<number>`, 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).