The node-engine seat's client asks a node once more when an event came while an ask ran, never dropping it (issue 1966 note 170; group with mesh-delivery)
#4
Merged
mesh-toolsmerged 1 commits from fix/1966-engine-reads-asked-again into main2026-11-10 10:45:50 +00:00
Issue 1966, note 170 (ruling and criteria: notes 172, 176). Group fix/1966-engine-reads-asked-again: this member and mesh-delivery (the assigner's test step), one check.
The fault, met a third time (2026-11-08, 2026-11-09 23:21 UTC, 2026-11-10): ace's node-engine stated its manifest reads at its start (9 bootstrapped seats, 07:36:26 UTC) and again 4 s later (60 seats); the assigner kept the first and held mesh-delivery #200's assigner build on ace under rule 7 until a hand ask-again at 10:16 UTC. Likely cause (not provable live: the ask-again overwrote the key): enginereads Keeper.AskNode dropped an ask of a node while one ran, so the restatement's ask was lost behind the start's.
What changes (go/clients/nodeengineclient/enginereads only, the seat's client; design 20 'Where a seat's code goes', ADR 0634 §1): an ask that arrives while one of the same node runs is marked and asked once more after it ends, one follow-up however many arrive, said in one journal line; a new Statement.EventAt (event-at) shows when the last event for the node was heard, cleared by Forget and by Heard's delete path. The assigner, the builder and the indexer read through this client, so all three are fixed; the builder and indexer need no change (their follow-ups are guarded by !Asking). No seat, event, state or manifest changes.
Quick or thorough: quick = the hand ask-again (done 10:16 UTC). Chosen = this, the kind's fix in its one shared place. Thorough, left to the joint milestone (W5) as a decision record: the event manifest-reads-changed carries the statement with stated-at and readers take it from the event (changes ADR 0618 §4, ADR 0668 §4). A rule ordering answers by the engine's StatedAt was built and dropped in review (a clock stepping back would refuse every newer statement; AC170-2 withdrawn).
Acceptance criteria: 1966/AC170-1 and AC170-3 (unit, a section of TestTheAnswerAndTheEventAreJudged; fails without coalescing); 1966/AC170-4 (integration, the mesh-delivery member). Checked beside mesh-sdk 3176059, mesh-catalog bfa4a085 and mesh-delivery at the group's head: go vet both ways clean, go test -race passes, seatgen -check exits 0; 71 unit test functions (unchanged).
Reviewed-by: mesh-code-reviewer@shanks (for lead-47@shanks) at c9ffed7042 (round 1: one finding, fixed; round 2: approve)
Issue 1966, note 170 (ruling and criteria: notes 172, 176). Group fix/1966-engine-reads-asked-again: this member and mesh-delivery (the assigner's test step), one check.
The fault, met a third time (2026-11-08, 2026-11-09 23:21 UTC, 2026-11-10): ace's node-engine stated its manifest reads at its start (9 bootstrapped seats, 07:36:26 UTC) and again 4 s later (60 seats); the assigner kept the first and held mesh-delivery #200's assigner build on ace under rule 7 until a hand ask-again at 10:16 UTC. Likely cause (not provable live: the ask-again overwrote the key): enginereads Keeper.AskNode dropped an ask of a node while one ran, so the restatement's ask was lost behind the start's.
What changes (go/clients/nodeengineclient/enginereads only, the seat's client; design 20 'Where a seat's code goes', ADR 0634 §1): an ask that arrives while one of the same node runs is marked and asked once more after it ends, one follow-up however many arrive, said in one journal line; a new Statement.EventAt (event-at) shows when the last event for the node was heard, cleared by Forget and by Heard's delete path. The assigner, the builder and the indexer read through this client, so all three are fixed; the builder and indexer need no change (their follow-ups are guarded by !Asking). No seat, event, state or manifest changes.
Quick or thorough: quick = the hand ask-again (done 10:16 UTC). Chosen = this, the kind's fix in its one shared place. Thorough, left to the joint milestone (W5) as a decision record: the event manifest-reads-changed carries the statement with stated-at and readers take it from the event (changes ADR 0618 §4, ADR 0668 §4). A rule ordering answers by the engine's StatedAt was built and dropped in review (a clock stepping back would refuse every newer statement; AC170-2 withdrawn).
Acceptance criteria: 1966/AC170-1 and AC170-3 (unit, a section of TestTheAnswerAndTheEventAreJudged; fails without coalescing); 1966/AC170-4 (integration, the mesh-delivery member). Checked beside mesh-sdk 3176059, mesh-catalog bfa4a085 and mesh-delivery at the group's head: go vet both ways clean, go test -race passes, seatgen -check exits 0; 71 unit test functions (unchanged).
Reviewed-by: mesh-code-reviewer@shanks (for lead-47@shanks) at c9ffed70421a43138eb23daf61debea4f8e4a8aa (round 1: one finding, fixed; round 2: approve)
https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
An event of manifest-reads-changed heard while an ask of the same node ran was dropped
without a line, so a restated engine could stay read at its first statement (ace,
2026-11-10 07:36). Every reader goes through Keeper.AskNode, so the assigner, the
builder and the indexer are fixed at once (ADR 0668 §4: the caller hears it and calls
again; ADR 0634 §1: the seat's client).
- AskNode: an ask while one runs is asked once more after it, one follow-up however
many came, said in one line (1966/AC170-1, AC170-3). The asks of one node so run one
after another, and take keeps the last answer, as before (no rule on the engine's
clock: review round 1).
- Statement.EventAt (event-at): when the node's event was last heard, read by the
parts' engine-reads tools; forgotten with the node's key.
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
Deliverynovox/mesh-contracts@c9ffed70421a — merged since 2026-11-10T10:45:51Z
Source — source.main moved to novox/mesh-contracts@f5d76e84ca. Whether it reached the machines is mesh-delivery-view's, derived from source.main, the wants and the haves.
2026-11-10 10:43 (new) → proposed (announced): novox/mesh-contracts#4's head announced
2026-11-10 10:43 proposed → ready (accepted): a verdict names this commit and the trunk's head as its trunk commit, the gate passed or warned, and the repository's own check did not fail; or the check gates no merge (check-gates-merge false)
2026-11-10 10:45 ready → merged (merged): on the trunk its modules follow: merged there
The commit's note under refs/notes/mesh-plan keeps every transition of this change up to its merge: git log --notes=mesh-plan.
<!-- mesh-delivery:view -->
**Delivery** `novox/mesh-contracts@c9ffed70421a` — **merged** since 2026-11-10T10:45:51Z
**Source** — source.main moved to novox/mesh-contracts@f5d76e84ca71. Whether it reached the machines is `mesh-delivery-view`'s, derived from `source.main`, the wants and the haves.
**Group** `fix/1966-engine-reads-asked-again`: novox/mesh-contracts@c9ffed70421a, novox/mesh-delivery@1a6144aa352b
**Transitions**
- 2026-11-10 10:43 (new) → proposed (announced): novox/mesh-contracts#4's head announced
- 2026-11-10 10:43 proposed → ready (accepted): a verdict names this commit and the trunk's head as its trunk commit, the gate passed or warned, and the repository's own check did not fail; or the check gates no merge (check-gates-merge false)
- 2026-11-10 10:45 ready → merged (merged): on the trunk its modules follow: merged there
The commit's note under `refs/notes/mesh-plan` keeps every transition of this change up to its merge: `git log --notes=mesh-plan`.
mesh-delivery: the operator's Approve of this pull request's merge into main is ended: a head it covers moved on: the heads it covers are no longer the group's heads. Nothing is merged on it. The operator is asked again once the checks pass at the new head.
mesh-delivery: the operator's Approve of this pull request's merge into main is ended: a head it covers moved on: the heads it covers are no longer the group's heads. Nothing is merged on it. The operator is asked again once the checks pass at the new head.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Issue 1966, note 170 (ruling and criteria: notes 172, 176). Group fix/1966-engine-reads-asked-again: this member and mesh-delivery (the assigner's test step), one check.
The fault, met a third time (2026-11-08, 2026-11-09 23:21 UTC, 2026-11-10): ace's node-engine stated its manifest reads at its start (9 bootstrapped seats, 07:36:26 UTC) and again 4 s later (60 seats); the assigner kept the first and held mesh-delivery #200's assigner build on ace under rule 7 until a hand ask-again at 10:16 UTC. Likely cause (not provable live: the ask-again overwrote the key): enginereads Keeper.AskNode dropped an ask of a node while one ran, so the restatement's ask was lost behind the start's.
What changes (go/clients/nodeengineclient/enginereads only, the seat's client; design 20 'Where a seat's code goes', ADR 0634 §1): an ask that arrives while one of the same node runs is marked and asked once more after it ends, one follow-up however many arrive, said in one journal line; a new Statement.EventAt (event-at) shows when the last event for the node was heard, cleared by Forget and by Heard's delete path. The assigner, the builder and the indexer read through this client, so all three are fixed; the builder and indexer need no change (their follow-ups are guarded by !Asking). No seat, event, state or manifest changes.
Quick or thorough: quick = the hand ask-again (done 10:16 UTC). Chosen = this, the kind's fix in its one shared place. Thorough, left to the joint milestone (W5) as a decision record: the event manifest-reads-changed carries the statement with stated-at and readers take it from the event (changes ADR 0618 §4, ADR 0668 §4). A rule ordering answers by the engine's StatedAt was built and dropped in review (a clock stepping back would refuse every newer statement; AC170-2 withdrawn).
Acceptance criteria: 1966/AC170-1 and AC170-3 (unit, a section of TestTheAnswerAndTheEventAreJudged; fails without coalescing); 1966/AC170-4 (integration, the mesh-delivery member). Checked beside mesh-sdk 3176059, mesh-catalog bfa4a085 and mesh-delivery at the group's head: go vet both ways clean, go test -race passes, seatgen -check exits 0; 71 unit test functions (unchanged).
Reviewed-by: mesh-code-reviewer@shanks (for lead-47@shanks) at
c9ffed7042(round 1: one finding, fixed; round 2: approve)https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
Delivery
novox/mesh-contracts@c9ffed70421a— merged since 2026-11-10T10:45:51ZSource — source.main moved to novox/mesh-contracts@f5d76e84ca. Whether it reached the machines is
mesh-delivery-view's, derived fromsource.main, the wants and the haves.Group
fix/1966-engine-reads-asked-again: novox/mesh-contracts@c9ffed7042, novox/mesh-delivery@1a6144aa35Transitions
The commit's note under
refs/notes/mesh-plankeeps every transition of this change up to its merge:git log --notes=mesh-plan.mesh-delivery: the operator's Approve of this pull request's merge into main is ended: a head it covers moved on: the heads it covers are no longer the group's heads. Nothing is merged on it. The operator is asked again once the checks pass at the new head.