From 49e26f5d279def54be060ee92507d6de1ae8995f Mon Sep 17 00:00:00 2001 From: jochen Date: Thu, 12 Nov 2026 05:00:12 +0100 Subject: [PATCH] Kept: the operator-channel client keeps an asked call's act, arguments and recorded mark MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit An asker that asks for a call (the tool runner's approval gate) keeps beside the ask the act its options bind, the call's whole arguments, and whether its run is in the hand-act log; Take keeps all three as it marks the ask. Builds: design 46 7-approval-mark §13 Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h --- .../go/clients/operatorchannelclient/client.go | 9 +++++++++ .../go/clients/operatorchannelclient/client_test.go | 12 ++++++++++++ 2 files changed, 21 insertions(+) diff --git a/operator-and-conversation/go/clients/operatorchannelclient/client.go b/operator-and-conversation/go/clients/operatorchannelclient/client.go index 01f974e..6f656aa 100644 --- a/operator-and-conversation/go/clients/operatorchannelclient/client.go +++ b/operator-and-conversation/go/clients/operatorchannelclient/client.go @@ -58,12 +58,21 @@ func (c *Client) now() time.Time { } // Kept is one ask as the module keeps it. +// +// An asker that asks for a call keeps beside it the act the ask binds, the call's whole arguments, and whether the act's +// run was recorded in the hand-act log (design 46 7-approval-mark §13): Take keeps all three as it marks the ask. type Kept struct { Ask seat.Ask `json:"ask"` Asked time.Time `json:"asked"` Acted bool `json:"acted,omitempty"` Ended string `json:"ended,omitempty"` Answer *seat.Warrant `json:"answer,omitempty"` + // Act is the act the ask's options bind, as its asker digested it. + Act Act `json:"act,omitempty"` + // Arguments are the asked call's arguments whole. + Arguments json.RawMessage `json:"arguments,omitempty"` + // Recorded says the act's run is in the hand-act log (`mesh-hand-acts.warranted` answered). + Recorded bool `json:"recorded,omitempty"` } func (c *Client) key(id string) string { return c.KeyPrefix + "ask." + id } diff --git a/operator-and-conversation/go/clients/operatorchannelclient/client_test.go b/operator-and-conversation/go/clients/operatorchannelclient/client_test.go index 02d6bb0..000c2ca 100644 --- a/operator-and-conversation/go/clients/operatorchannelclient/client_test.go +++ b/operator-and-conversation/go/clients/operatorchannelclient/client_test.go @@ -167,9 +167,21 @@ func TestAKeyPrefixIsPutBeforeEveryKeyOfTheClientsOwnStateAndNotBeforeWhere(t *t if _, ok := store.vals[tc.key]; len(store.vals) != 1 || !ok { t.Fatalf("prefix %q: keys written %v, want %s", tc.prefix, store.vals, tc.key) } + // Design 46 7-approval-mark §13: the act and the call's arguments kept beside the ask stay as Take marks it. + e, _ := store.Get(tc.key) + var k Kept + _ = json.Unmarshal(e.Value, &k) + k.Act, k.Arguments = releaseHQ, json.RawMessage(`{"delivery":"hq"}`) + if _, err := store.Update(tc.key, k, e.Revision); err != nil { + t.Fatal(err) + } if h, err := c.Take(askedWarrant(), func(seat.Option, seat.Warrant) error { return nil }); h != Acted || err != nil { t.Fatalf("prefix %q: the warrant was not read from %s: %s %v", tc.prefix, tc.key, h, err) } + raw := string(store.vals[tc.key]) + if !strings.Contains(raw, `"act":{"delivery":"hq","verb":"release"}`) || !strings.Contains(raw, `"arguments":{"delivery":"hq"}`) || strings.Contains(raw, `"recorded"`) { + t.Errorf("prefix %q: the kept ask after Take is %s", tc.prefix, raw) + } if _, _, err := c.Where("an-asker.d-1"); err != nil || asked != "an-asker.d-1" { t.Errorf("prefix %q: Where read %q", tc.prefix, asked) }