J3 (A2g ruling): a reader's again tool records its hand act through mesh-hand-acts before it asks
StatusTools takes the reader's handacts.Recorder: again records the act through seat:mesh-hand-acts.hand-act before it writes the hand ask, and refuses, asking nothing, when the seat does not take it, as the stdio Reader's again does. Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
This commit is contained in:
+9
-2
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/nats-io/nats.go/jetstream"
|
||||
|
||||
stdio "git.novox.be/novox/mesh-sdk/go"
|
||||
"git.novox.be/novox/mesh-sdk/go/handacts"
|
||||
)
|
||||
|
||||
// StatusState is a reader's own state of its first views (design 25 § 12.2): at StatusKey each first view's Status, as
|
||||
@@ -92,8 +93,10 @@ func HearAgain(ctx context.Context, kv jetstream.KeyValue, followers []*Follower
|
||||
|
||||
// StatusTools are a reader's read tool of its first views (read) and its re-read tool (again), in its tools bundle,
|
||||
// over its StatusState: read lists what the process last said of each; again writes a hand ask the process takes,
|
||||
// naming the caller the runtime proved, and is recorded in the status's by-hand count and why.
|
||||
func StatusTools(reader, read, again string, st stdio.KeptState, now func() time.Time) []stdio.Tool {
|
||||
// naming the caller the runtime proved, and is recorded in the status's by-hand count and why. again is a hand act:
|
||||
// acts records it through the seat mesh-hand-acts before the ask is written, and one the seat does not take is said and
|
||||
// nothing is asked (the zero Recorder records nothing, so again refuses).
|
||||
func StatusTools(reader, read, again string, st stdio.KeptState, acts handacts.Recorder, now func() time.Time) []stdio.Tool {
|
||||
return []stdio.Tool{
|
||||
{Name: read,
|
||||
Description: fmt.Sprintf("%s's first views of the indexer's and the assigner's states (novox/hq ADR 0615): per owner and state, "+
|
||||
@@ -136,6 +139,10 @@ func StatusTools(reader, read, again string, st stdio.KeptState, now func() time
|
||||
return nil, errors.New("again names the owner, the state and why")
|
||||
}
|
||||
a := HandAsk{V: Version, Owner: owner, State: state, Why: strings.TrimSpace(why), By: stdio.CallerOf(args), At: now().UTC()}
|
||||
if _, err := acts.Record(handacts.Request{What: fmt.Sprintf("asked %s's first view of %s's %s again by hand", reader, owner, state),
|
||||
Why: a.Why, Cause: "first-view-again", Verb: again}); err != nil {
|
||||
return nil, fmt.Errorf("the hand act was not recorded through mesh-hand-acts, so nothing was asked again: %w", err)
|
||||
}
|
||||
if _, err := st.Put(AgainKey(owner, state), a); err != nil {
|
||||
return nil, fmt.Errorf("the hand ask is not written: %w", err)
|
||||
}
|
||||
|
||||
@@ -314,6 +314,33 @@ func TestViews(t *testing.T) {
|
||||
}
|
||||
_ = w.Stop()
|
||||
})
|
||||
t.Run("a reader's again tool records its hand act through mesh-hand-acts before it writes the ask, and asks nothing when the seat does not take it", func(t *testing.T) {
|
||||
var recorded []handacts.Request
|
||||
take := errors.New("no responders")
|
||||
acts := handacts.Recorder{Ask: func(key string, body any) (json.RawMessage, error) {
|
||||
if key != "seat:mesh-hand-acts.hand-act" {
|
||||
return nil, fmt.Errorf("asked %s", key)
|
||||
}
|
||||
raw, _ := json.Marshal(body)
|
||||
var q handacts.Request
|
||||
_ = json.Unmarshal(raw, &q)
|
||||
recorded = append(recorded, q)
|
||||
if take != nil {
|
||||
return nil, take
|
||||
}
|
||||
return json.RawMessage(`{"log":"mesh-hand-acts"}`), nil
|
||||
}}
|
||||
again := StatusTools("reader", "reader_first_views", "reader_first_view_again", stdio.State(StatusState), acts, now)[1]
|
||||
args := map[string]any{"owner": "o", "state": "modules", "why": "doubted"}
|
||||
if _, err := again.Run(args); err == nil || !strings.Contains(err.Error(), "nothing was asked again") || len(recorded) != 1 {
|
||||
t.Errorf("a hand act the seat did not take: %v, recorded %v", err, recorded)
|
||||
}
|
||||
take = nil // taken: the ask is written next (here refused, for no runtime serves this test)
|
||||
if _, err := again.Run(args); err == nil || !strings.Contains(err.Error(), "hand ask is not written") || len(recorded) != 2 ||
|
||||
recorded[1].Why != "doubted" || recorded[1].Verb != "reader_first_view_again" || !strings.Contains(recorded[1].What, "o's modules") {
|
||||
t.Errorf("a hand act taken: %v, recorded %+v", err, recorded)
|
||||
}
|
||||
})
|
||||
t.Run("an ask through a tool reads the answer bare or in the tool runner's envelope, and its error", func(t *testing.T) {
|
||||
bare := `{"v":1,"owner":"o","state":"s","revision":3,"values":{"k":"1"}}`
|
||||
for name, c := range map[string]struct {
|
||||
|
||||
Reference in New Issue
Block a user