The controller-merges consumer (no max-deliver, one at a time) held the de-spiegel merge e25e1beb from 10-29 09:39: keepForgeMerge put an announcement with its Paths into delivery-merges (16 KiB values), got 10054, retried "not now" forever, and 167 merges queued behind it. Every five-minute hold outran the deaf bound, so core.controller.deaf flapped. Merges are mesh-delivery's: the gate merges on the Approve and the forge bridge says each merge on its stream FORGE (pull request, head, merge commit), kept a week. The controller's copy was a leftover, read only at a moved module's registration (ADR 0420 §7, ADR 0432). That read now finds the merge on FORGE; the consumer, its follow, its handler and its hold delays are removed, and every assertion removes the retired consumer from the bus. Kind fix for the watchdog: the event loop records when a message it held back is due again, and deafness counts from then, so no hold longer than the bound (on any consumer) reads as deafness. Quick fix: strip Paths from the kept announcement and add max-deliver with a dead letter. Thorough fix: remove the duplicate duty and make the deaf watchdog hold-aware. Chose thorough: the controller is being deprecated and the merges already have an owner; the hold-vs-deaf confusion is a kind, not one consumer. Research 072 piece: 03-domains (Control shrinks to placement and composition; the delivery parts own what a merge is) and milestone 3 (health signals stop sharing the controller's loop assumptions).
63 lines
4.6 KiB
Go
63 lines
4.6 KiB
Go
package link
|
||
|
||
// The contract of every message kind the controller consumes (novox/hq to-be 45 Phase 2, ADR 0227 rule
|
||
// 2 "how it is checked": a contract test per consumed message kind in the receiver's repository, and a
|
||
// check listing every consumed subject against the tests that name it).
|
||
//
|
||
// **Each kind says how an older one is told from a newer, and the tests that deliver n, then n−1.** A
|
||
// kind that carries no order says why none is needed — a word whose newest is simply the latest heard,
|
||
// a request answered once. The test beside it fails a kind the controller can be handed without an
|
||
// entry here, and an entry naming a test that does not exist.
|
||
|
||
// Contract is one consumed kind's order.
|
||
type Contract struct {
|
||
// Ordered is how an older message of this kind is refused; empty for a kind that carries no order.
|
||
Ordered string
|
||
// Unordered is why a kind needs no order; empty for an ordered one.
|
||
Unordered string
|
||
// Tests are the tests that deliver the newer and then the older, and assert the older refused.
|
||
Tests []string
|
||
}
|
||
|
||
// Contracts are every kind the controller consumes, by kind.
|
||
var Contracts = map[string]Contract{
|
||
KindReport: {Ordered: "by the epoch and sequence of the declaration it is about, then the node-engine's " +
|
||
"report sequence (order.go); an older account is refused and counted. A report from a node-engine " +
|
||
"that orders nothing is judged by the digest it names (issue 267)",
|
||
Tests: []string{"TestAnAccountOfAnOlderDeclarationIsRefusedByItsSequence",
|
||
"TestAnOlderReportOfTheSameDeclarationIsRefused", "TestAnAccountOfAnOlderDeclarationIsRefusedByItsSequence",
|
||
"TestAnAccountIsOlderByEpochThenSequenceThenReportSequence"}},
|
||
KindBuilt: {Unordered: "a build's outcome on the retired build seat's subjects: dropped, nothing takes a build in " +
|
||
"from the bus any more (R4g, ADR 0501 §1); the subjects stay followed while the installer's carried user list " +
|
||
"names them"},
|
||
KindSourceMoved: {Unordered: "the forge's merge on EVENTS: no longer followed, dropped if one arrives; the forge " +
|
||
"bridge's stream FORGE is the record of the merges, read at a moved module's registration (sweep 2026-10-30)"},
|
||
KindToolsHeartbeat: {Unordered: "a word that the node tools are there, as a machine's heartbeat"},
|
||
KindHealth: {Ordered: "by the time the node-engine looked (`at`, on the machine's clock): a statement older " +
|
||
"than the one kept for that machine is refused, so an event arriving after a newer report does not undo it " +
|
||
"(novox/hq ADR 0240)",
|
||
Tests: []string{"TestAnOlderHealthStatementIsRefused"}},
|
||
KindEnrolment: {Unordered: "a request answered once, under a token spent once: a second presentation is " +
|
||
"refused by the token, not by an order (issue 083)",
|
||
Tests: []string{"TestAnEnrolmentMetByAHeldTokenIsAskedToTryAgain"}},
|
||
KindModuleMoved: {Unordered: "the catalogue saying a module's current build moved: acted on by reading the " +
|
||
"catalogue's record, which is the order, so a late one reads the same record"},
|
||
KindPullUpdated: {Unordered: "a pull request's head, asked to be checked: each head is its own commit, and its " +
|
||
"verdict is set on that commit alone, so a head heard late is checked and judged as itself and never " +
|
||
"stands for a newer one (novox/hq to-be 45 §9)"},
|
||
KindDecided: {Unordered: "the router's word on one ask, by the ask's id: an ask is ended once, by compare-and-set " +
|
||
"at the router, and the controller acts on it once, recording that it did under the ask's id — so a word " +
|
||
"heard again, or late, does nothing more (novox/hq ADR 0259)",
|
||
Tests: []string{"TestAWarrantIsActedOnOnce"}},
|
||
KindDeliveryMerged: {Unordered: "mesh-delivery's word that it merged a pull request, by the pull request and its head: " +
|
||
"kept under that key once, so a word heard again or late rewrites the same value (novox/hq ADR 0420 §7)"},
|
||
KindCatchUp: {Unordered: "a catalogue asking what it missed: answered from the record, whenever asked"},
|
||
KindProvisioner: {Unordered: "a provider's newest word about a consumer, said again every fifteen minutes " +
|
||
"while it holds (ADR 0224): the condition keeps the last observed, and S8 says when the words stop. " +
|
||
"Its retirement word (ADR 0230) is unordered too: a waiting set is said again every fifteen minutes, " +
|
||
"and every other change is checked against the provider itself — `retire` and `cleanup` ask it, " +
|
||
"and the self-check's D11 asks it every run — so an older word read late is corrected by the next",
|
||
Tests: []string{"TestAProviderFailingAConsumerBreaksAllWellUntilItRecovers",
|
||
"TestARetirementWordIsKeptAsItsConditionNamingTheEmitterFromTheSubject"}},
|
||
}
|