Kept calls in the assigner, teller, builder and indexer; take-in judges what it writes; hand tools for each recovery (ADR 0668; issue 1966; group fix/1966-call-made-once) #199

Merged
mesh-tools merged 22 commits from fix/1966-call-made-once into main 2026-11-10 07:20:35 +00:00
Member

Member of group fix/1966-call-made-once (mesh-sdk #185 merges first; mesh-contracts, mesh-host). The full description, tests, validator verdicts and review record are on mesh-sdk #185.

This member: the assigner reads operator-channel's asks at its consumer's bind and asks again an ask that ended, gains assigner_ask_again; the teller keeps a failed assigner-ask publish; the builder's ask put is a kept call, a key left building is call-unanswered and builder_build_again takes it; the indexer's merge message is a kept call (unread, not lost; call-unanswered while the forge is heard), indexer_drop_pending refuses a merge no later merge covers (changes ADR 0633 §5), a take-in waits for the verdicts state and keeps its new manifests unjudged until judged (indexer_read_unjudged), a judge by digest of the trunk's manifest says its event; the indexer and the builder write call-unanswered for manifest-reads and ask mesh-watchdogs.presence (no read of the watchman's state, ADR 0596 §2); the watchman serves presence by machine.

Issue 1966 (notes 152-160); decision ADR 0668 (accepted).

Reviewed-by: mesh-code-reviewer@shanks (3 rounds and a narrow check of round 3's fixes) at mesh-sdk 13998c2362d35f0d150e5cdc2d6234800fb5519e, mesh-contracts bb16f99e2d5e854bb8f6552ce4b256e7c10e8ea0, mesh-host 9cd03a7430cc6b7dca3f5a97a08a5a799a84c673, mesh-delivery 262d21c431
Pushed-by: lead-47@shanks

https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ

Member of group fix/1966-call-made-once (mesh-sdk #185 merges first; mesh-contracts, mesh-host). The full description, tests, validator verdicts and review record are on mesh-sdk #185. This member: the assigner reads operator-channel's asks at its consumer's bind and asks again an ask that ended, gains assigner_ask_again; the teller keeps a failed assigner-ask publish; the builder's ask put is a kept call, a key left building is call-unanswered and builder_build_again takes it; the indexer's merge message is a kept call (unread, not lost; call-unanswered while the forge is heard), indexer_drop_pending refuses a merge no later merge covers (changes ADR 0633 §5), a take-in waits for the verdicts state and keeps its new manifests unjudged until judged (indexer_read_unjudged), a judge by digest of the trunk's manifest says its event; the indexer and the builder write call-unanswered for manifest-reads and ask mesh-watchdogs.presence (no read of the watchman's state, ADR 0596 §2); the watchman serves presence by machine. Issue 1966 (notes 152-160); decision ADR 0668 (accepted). Reviewed-by: mesh-code-reviewer@shanks (3 rounds and a narrow check of round 3's fixes) at mesh-sdk 13998c2362d35f0d150e5cdc2d6234800fb5519e, mesh-contracts bb16f99e2d5e854bb8f6552ce4b256e7c10e8ea0, mesh-host 9cd03a7430cc6b7dca3f5a97a08a5a799a84c673, mesh-delivery 262d21c431b3682f91190363689ab8f58cdb5032 Pushed-by: lead-47@shanks https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
mesh-tools added 22 commits 2026-11-10 04:12:55 +00:00
Note 155: a manifest-reads-changed said before the assigner's consumer existed was never heard, and
ace's bootstrapped statement stood. Each part registers the engine-reads keeper's AtBind on its hub
and calls the verb as a kept call (CallKeptOn). The asks-at-bind half (Q7) is not in this commit.

Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
#650, its repository's head, was dropped on the advice of a line that named a drop where nothing
covered it; its changes would never have been taken in. The rule lived only in the record and the
advice; the tool now checks it, and the advice names the read again.

Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
An ask-ended the teller said before the assigner's consumer existed is not delivered to it (note 155).
At each bind the assigner calls the seat verb operator-channel.asks once, a kept call, for the ended
asks since its earliest held asking, and writes again each one that ended expired or cancelled, by
the ask-ended rules and their compare-and-set. A seat verb: no module named. One invoke added.

Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
The indexer's call for a merged message is a kept call (CallKept). A load that met a deadline or no
responders keeps the entry as unread (Pending.Unread, indexer_pending's unread), with a line that
names the read again rather than a drop; after every message heard on FORGE, of any kind, an unread
merge is evaluated again. The bridge's own answer stays lost. indexer_take_in_pending already reads
the message again (Q8).

Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
The recovery of an ask that ended at the channel unheard needed a restart. The tool writes the key
again under a new asking by the ask-ended rules (a proposal's authorising ask and a put's record ask
are refused), refuses an asking the operator answered, naming the answer, and records the hand act
through the seat mesh-hand-acts. One tool added to the manifest.

Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
A failed publish deleted the kept record for "the next writing of the key", which nothing made.
The ask now joins the teller's wait for room, kept on the bus, which asks again at the next end
and at the start. The gate's asks are left as they are (ADR 0666 §6 replaces them).

Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
The put carries the ask's id as its message id, so it is made again through a deadline and no responders within the bound;
a put or a note that still meets one fails the key as a transport fault, which the builder does not retake by itself
(ADR 0664 §3) and the hand tool does. A key left building with no look holding it (its end never written: "claimed", no
ask) is taken as it stands by builder_build_again, from another builder too.

Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
The look arms a key of the state bounds with its own time to live; the bus's marker of its end raises call-unanswered
about the build key while it is still building and no look holds it, naming builder_build_again; the key's next written
end deletes the bound and clears the finding. A bound that cannot be written raises at once. No timer.

Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
A take-in whose judge pass fails is judged again at the next message heard, as a failed start pass is.

Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
A judge pass that failed lost the set of manifests the take-in newly wrote, which
lived only in its memory: the next pass found no verdict, took each as accepted
before any verdict (ADR 0579 §1), and wrote a refusal as a warning. The take-in
now keeps each new digest in the indexer's own state unjudged before it writes
the module naming it; every judge pass judges those as fresh and ends a key once
its verdict is written or no module holds it. indexer_read_unjudged reads the
state; indexer_judge judges it again by hand.

Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
Without the unjudged state the bind's pass accepted the refused manifest with a
warning and the waiting one, and said manifest-accepted for both; the row settles
Q3: the indexer says what grants follows, so the grants part is unchanged (no D8).

Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
A message heard on the forge is the forge bridge heard, the callee of the call:
after each one a merge unread since CallUnansweredAfter or longer writes the
finding naming the bridge's call, and a merge no longer unread clears it. While
nothing is heard on the forge (the bridge's machine away) no finding is written;
the merge is read again when the forge is heard. No timer.

Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
indexer_judge with a digest and the start pass's judgeStale wrote the verdict and said nothing, so a part waiting on manifest-accepted never heard it.

Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
The bind's read of the operator channel's asks is made again after every transport fault until answered; a node whose engine answers nothing while its machine is heard is asked again at each pass once its ask ended. Past CallUnansweredAfter with the callee's machine heard each writes the finding in the assigner's findings, cleared once answered; none while the machine is away.

Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
Both write it through buildrun.ReadsCalls over enginereads Keeper.Unanswered as the assigner does, read the watchman's presence for a machine heard, arm a bound key that expires at the five minutes (no timer) and clear the finding when the node answers or its machine is away.

Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
The builder and the indexer ask it whether a node's machine is heard instead of reading the watchman's state; key and prefix stay for the whole read.

Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
Both manifests drop the read mesh-delivery-watchman.presence and invoke seat:mesh-watchdogs.presence; buildrun's ReadsCalls, its presence bucket and both watchPresence copies go. The machine is asked once when the bound key expires; a node that returns is asked again on manifest-reads-changed, and the finding clears on its answer. The indexer's finding is stamped with the wait's clock.

Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
D14: the assigner keeps its manifest-reads wait through the node-engine seat's client's ReadsCalls, its own copy gone (issue 1966, ADR 0668 §3, ADR 0634 §1; review round 3, finding 2)
mesh/check checking 262d21c431b3 on ee3906bb19ba | novox/mesh-delivery#199 in group fix/1966-call-made-once
mesh/delivery-group group fix/1966-call-made-once merged: every member is merged
mesh/delivery merged: source.main moved to novox/mesh-delivery@ee3906bb19ba
262d21c431
Its presence says heard at each pass, so it keeps no bound; the findings it holds from an earlier process are weighed through Held.

Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
Author
Member

Delivery novox/mesh-delivery@262d21c431b3 — merged since 2026-11-10T07:20:37Z

Source — source.main moved to novox/mesh-delivery@ee3906bb19. Whether it reached the machines is mesh-delivery-view's, derived from source.main, the wants and the haves.

Group fix/1966-call-made-once: novox/mesh-contracts@bb16f99e2d, novox/mesh-delivery@262d21c431, novox/mesh-host@d581acdeda, novox/mesh-sdk@32b14ce0ef

  • composed together: fail — the checker's verdict at the members' heads (6985553d412c): mesh-delivery-checker

Transitions

  • 2026-11-10 04:12 (new) → proposed (announced): novox/mesh-delivery#199's head announced
  • 2026-11-10 04:13 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 07:20 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-delivery@262d21c431b3` — **merged** since 2026-11-10T07:20:37Z **Source** — source.main moved to novox/mesh-delivery@ee3906bb19ba. Whether it reached the machines is `mesh-delivery-view`'s, derived from `source.main`, the wants and the haves. **Group** `fix/1966-call-made-once`: novox/mesh-contracts@bb16f99e2d5e, novox/mesh-delivery@262d21c431b3, novox/mesh-host@d581acdedae3, novox/mesh-sdk@32b14ce0ef4b - composed together: fail — the checker's verdict at the members' heads (6985553d412c): mesh-delivery-checker **Transitions** - 2026-11-10 04:12 (new) → proposed (announced): novox/mesh-delivery#199's head announced - 2026-11-10 04:13 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 07:20 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`.
Author
Member

mesh-delivery: the operator's Approve of this pull request's merge into main is ended: its head 9cd03a7430cc is no longer the pull request's head, or the pull request closed. 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: its head 9cd03a7430cc is no longer the pull request's head, or the pull request closed. Nothing is merged on it. The operator is asked again once the checks pass at the new head.
mesh-tools merged commit ee3906bb19 into main 2026-11-10 07:20:35 +00:00
mesh-tools deleted branch fix/1966-call-made-once 2026-11-10 07:20:35 +00:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: novox/mesh-delivery#199