diff --git a/04-ISSUES/348-a-resolver-that-stopped-answering-ran-on-unnoticed-and-builds-sent-after-it-were-blamed/01-diagnosis.md b/04-ISSUES/348-a-resolver-that-stopped-answering-ran-on-unnoticed-and-builds-sent-after-it-were-blamed/01-diagnosis.md index 9ca4d796..00a9e8ce 100644 --- a/04-ISSUES/348-a-resolver-that-stopped-answering-ran-on-unnoticed-and-builds-sent-after-it-were-blamed/01-diagnosis.md +++ b/04-ISSUES/348-a-resolver-that-stopped-answering-ran-on-unnoticed-and-builds-sent-after-it-were-blamed/01-diagnosis.md @@ -173,3 +173,6 @@ registry, is the operator's decision. | live | after delivery: `dnsmasq_health` on both resolvers healthy; a restart by the watch said as `restarted` on the bus | A replay in mesh-lab's register is still owed before this core issue resolves (ADR 0237). + +The controller's own test of the resolver's manifest (`TestTheResolverForwardsToFixedUpstreamsAndNeverReadsResolvConf`) +now asks for `bind-interfaces` and refuses `bind-dynamic`, so the two pull requests land together. diff --git a/04-ISSUES/349-a-merge-acted-on-late-superseded-the-merge-after-it-and-built-the-older-commit/00-report.md b/04-ISSUES/349-a-merge-acted-on-late-superseded-the-merge-after-it-and-built-the-older-commit/00-report.md new file mode 100644 index 00000000..29602fb9 --- /dev/null +++ b/04-ISSUES/349-a-merge-acted-on-late-superseded-the-merge-after-it-and-built-the-older-commit/00-report.md @@ -0,0 +1,55 @@ +--- +status: located +opened: 2026-10-09 +located-in: [mesh-controller cmd/mesh-controller (release_plan.go supersededBy, upgrades.go), mesh-controller internal/inventory (release_plan)] +fixed-by: +amended-design: +--- + +# 349. A merge acted on late superseded the merge after it, and built the older commit + +## Symptom + +On 2026-10-09 the plans of the catalogue superseded each other out of the branch's order, twice +(`mesh-controller.plans`): + +- the plan at 1833045c was "superseded at tier 0 by" the plan at a783ac94, a merge made before it; +- the plan at a082615b — the merge of a security fix to the forge's module — was "superseded at tier 0 by" + the plan at 8ff8197a, the merge before it, with "gitea planned there again". The forge's module was then + to be built from the commit without the fix. A third merge (9e4267bf) came a minute later and superseded + that plan in turn, so the fix was built from 9e4267bf. Had nothing come after, it would not have been. + +## Why it is an issue + +A newer plan of a branch supersedes the older open ones and builds what they had not +([ADR 0218](../../02-DECISIONS/0218-a-plan-sends-grants-before-code-rolls-out-one-machine-first-and-a-newer-merge-takes-over-an-older-plan.md), +issue 254). "Newer" was read from when each plan was made, never from the commits. The catch-up acts on a +merge the bus did not hand over (issue 266) after the merges that came after it, so its plan was made last +and won. The mesh built an older commit than the branch held, and said nothing wrong: each plan said +"superseded", as designed. + +## Diagnosis + +The order of merges into one branch is the forge's: each merge is made on the branch as the one before +left it, so a later merge's commit contains every earlier one's, and the forge's merge time +(`merged_at`, which every announcement carries) is the branch's order. A plan kept none of it. +`supersededBy` compared `Created`. + +## Fix + +In mesh-controller, in the same pull request as issue 348 (PR 179): + +- A plan keeps when its merge was made (`merged_at`, migration 0086; null for a release and for a plan kept + before it). +- `supersededBy` orders two plans of a branch by their merge times where both are known, and by when they + were made only where one is not. +- A merge older than an open plan of its branch is planned at that plan's commit, which contains it, and + that plan is superseded by it as by any newer plan. What both merges moved is built once, from the newest + commit of the branch. + +## How it is checked + +`TestTwoMergesActedOnInReverseOrderBuildTheNewerCommit` replays the day's case: the later merge acted on +first, the earlier one second; one plan is left open, at the later commit, building what both moved. +`TestTheBranchOrderIsTheMerges` holds the order and the lookup. Both fail on the commit before the fix. +A replay in mesh-lab's register is still owed before this core issue resolves (ADR 0237).