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
22 Commits
Author SHA1 Message Date
jschoubben 262d21c431 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
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
2026-11-10 05:01:15 +01:00
jschoubben 98ffc1fb80 D13: the builder and the indexer ask the watchdogs seat's presence when a manifest-reads call's bound ends, through the node-engine seat's client's ReadsCalls, and read no watchman state (issue 1966, ADR 0596 §2, ADR 0668 §3, ADR 0634 §1; review round 3, findings 1 and 2)
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
2026-11-10 05:01:15 +01:00
jschoubben 8e426b236d D12: the watchman serves the watchdogs seat's presence with its declared machine, answering that machine's online and since in the seat's answer (issue 1966, ADR 0596 §2; review round 3, finding 1)
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
2026-11-10 04:55:31 +01:00
jschoubben 0f52bb80ad D11: the builder and the indexer say a manifest-reads call unanswered past five minutes, its machine heard, as call-unanswered in their own findings (issue 1966, ADR 0668 §3; review round 2)
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
2026-11-10 04:38:38 +01:00
jschoubben 00e84bb977 D10: the assigner calls the operator-channel seat's asks with its declared input and reads its declared answer (issue 1966, ADR 0668 §4; review round 1, finding 5)
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
2026-11-10 04:20:04 +01:00
jschoubben 23ddaa8bed D9: the assigner keeps the wait of its bind's asks read and of a heard node's manifest-reads, and says each unanswered past five minutes as call-unanswered (issue 1966, ADR 0668 §3; review round 1, finding 4)
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
2026-11-10 04:17:45 +01:00
jschoubben 8f50f22622 D8: a trunk's held manifest judged by its digest is said as manifest-accepted or manifest-refused, as the full pass says it (issue 1966, ADR 0668 §4; review round 1, finding 3)
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
2026-11-10 04:13:02 +01:00
jschoubben cddaf14cd0 D7a: the assigner, the indexer and the builder ask a node's manifest-reads once before the kept call, so a node that answers nothing reads as its fallback at once (issue 1966, ADR 0668 §3; review round 1, finding 1)
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
2026-11-10 04:11:07 +01:00
jschoubben bd39747c22 D1i: a row for the indexer's bind: every counted node's manifest-reads is called once (issue 1966 note 155, ADR 0668 §4)
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
2026-11-10 03:53:05 +01:00
jschoubben 17dd41696c D4f: a merged message still unread five minutes on, the forge heard, is the indexer's finding call-unanswered (issue 1966 note 153, ADR 0668 §3)
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
2026-11-10 03:52:04 +01:00
jschoubben 7b3f213ae8 D6i: a merge taken in before the verdicts state binds has each manifest judged as new and said at the bind, in the indexer's whole-module test (issue 1966 note 154, ADR 0668 §4)
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
2026-11-10 03:48:21 +01:00
jschoubben b48e9ca6ce D6k: keep a take-in's new manifests unjudged on the bus until a judge pass judges them (issue 1966, ADR 0668 §4)
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
2026-11-10 03:46:09 +01:00
jschoubben 9296db5538 D6: a take-in waits for the verdicts state, so every manifest it writes is judged in it before take-in.taken; its bind evaluates pending again (issue 1966 note 154, ADR 0668 §4)
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
2026-11-10 03:38:07 +01:00
jschoubben d3f68c5372 D5: indexer_drop_pending counts a later pending merge as covering only when its commit has the pending merge's as an ancestor (issue 1966, ADR 0668 §6, ADR 0633 §5)
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
2026-11-10 03:34:57 +01:00
jschoubben e4dabdbc7a D7: a build key a look left building because its end could not be written is call-unanswered after five minutes (issue 1966, 1748 note 27, ADR 0668 §3, §5)
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
2026-11-10 03:34:57 +01:00
jschoubben 0d16381b28 D7: the builder's ask put is a kept call, a put or note a transport fault kept from the key fails it in that fault's words, and builder_build_again takes a key left building (issue 1966, 1748 note 27, ADR 0668 §1, §2, §5)
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
2026-11-10 03:30:37 +01:00
jschoubben 3076aabbe0 D3: the teller keeps an assigner ask whose publish failed waiting, and asks it at the next end and at its start (issue 1966, ADR 0668 §1)
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
2026-11-10 03:17:50 +01:00
jschoubben f02a740b10 D2: assigner_ask_again asks one of the assigner's asks of the operator again by hand (issue 1966, ADR 0668 §5)
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
2026-11-10 03:16:28 +01:00
jschoubben c3b240bdfa D4: a merged message the forge bridge could not give for a transport fault is unread, not lost, and read again on the next message heard on the forge (issue 1966 note 153, ADR 0668 §1, §4)
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
2026-11-10 03:14:12 +01:00
jschoubben 3f2482716b Q7: the assigner reads the operator-channel seat's asks at its consumer's bind and asks again each held asking that lapsed or was cancelled (issue 1966, ADR 0668 §4)
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
2026-11-10 03:10:33 +01:00
jschoubben 7bdc41c0d3 D5: indexer_drop_pending refuses a merge no later merge covers, unless abandon (issue 1966, ADR 0633 §5, ADR 0668 §5)
#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
2026-11-10 03:01:38 +01:00
jschoubben 416e270899 D1: the assigner, builder and indexer call every node's manifest-reads again at their consumer's bind (issue 1966, ADR 0668 §4)
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
2026-11-10 02:59:53 +01:00