Merge pull request 'Record a module's act on the operator's warrant from the router's own record (hq ADR 0274)' (#194) from feat/warranted-hand-act into main
This commit was merged in pull request #194.
This commit is contained in:
@@ -338,6 +338,15 @@ var ControllerVerbs = []Verb{
|
||||
"why": "what the drill tests",
|
||||
"condition": "the key of the condition the drill is meant to raise, if any (optional)",
|
||||
}, []string{"what", "why"})},
|
||||
{Name: "warranted", Description: "Record in the hand-act log what a module did on the operator's warrant (novox/hq " +
|
||||
"ADR 0274, ADR 0259): who chose, through which channel, with which proofs and which answer are read from the " +
|
||||
"router's own record of that module's ask, never from the caller; recorded once per ask however often it is " +
|
||||
"asked; the caller names the ask and says nothing else. Refused for an ask still open, ended without a choice, " +
|
||||
"or not that module's.",
|
||||
Input: schema(map[string]string{
|
||||
"asker": "the module that asked, e.g. claude-code",
|
||||
"ask": "its ask's id",
|
||||
}, []string{"asker", "ask"})},
|
||||
{Name: "hand-acts", Description: "What was done by hand lately — pushes, plans ended, consumers re-made, acts " +
|
||||
"recorded — who, why and the cause of each, and which causes repeat: each repeat is a healer the mesh lacks.",
|
||||
Input: schema(map[string]string{"days": "how many days back (default 14)"}, nil)},
|
||||
|
||||
@@ -122,6 +122,33 @@ func RecordHandAct(ctx context.Context, conn *nats.Conn, act HandAct) (HandAct,
|
||||
return act, err
|
||||
}
|
||||
|
||||
// RecordHandActOnce writes one entry under the id it carries, only where none is: an act recorded once however
|
||||
// often it is asked, such as a module's act on a warrant, asked by each of its instances (novox/hq ADR 0274). It
|
||||
// answers false, with no error, when the entry was already there.
|
||||
func RecordHandActOnce(ctx context.Context, conn *nats.Conn, act HandAct) (bool, error) {
|
||||
if act.ID == "" || strings.TrimSpace(act.Why) == "" {
|
||||
return false, errors.New("an act recorded once carries its id and why")
|
||||
}
|
||||
if act.At.IsZero() {
|
||||
act.At = time.Now().UTC()
|
||||
}
|
||||
kv, err := handActs(ctx, conn)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
body, err := json.Marshal(act)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if _, err := kv.Create(ctx, act.ID, body); err != nil {
|
||||
if errors.Is(err, jetstream.ErrKeyExists) {
|
||||
return false, nil
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// HandActs is every entry since a moment, oldest first.
|
||||
func HandActs(ctx context.Context, conn *nats.Conn, since time.Time) ([]HandAct, error) {
|
||||
kv, err := handActs(ctx, conn)
|
||||
|
||||
@@ -57,3 +57,30 @@ func TestNatsAnActByHandIsKeptWithWhyAndARepeatIsFound(t *testing.T) {
|
||||
t.Fatalf("%q", acts[2].ID)
|
||||
}
|
||||
}
|
||||
|
||||
// An act on a warrant asked by each of a module's instances is recorded once (novox/hq ADR 0274).
|
||||
func TestNatsAnActRecordedOnceIsWrittenOnce(t *testing.T) {
|
||||
js := aBus(t)
|
||||
api, err := jetstream.New(js.Conn())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_ = api.DeleteKeyValue(t.Context(), broker.HandActsBucket)
|
||||
if err := js.EnsureControllerBuckets(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
act := HandAct{ID: "warrant-claude-code-instr-1", Verb: "warrant", Why: "the operator chose Approve", By: "the operator"}
|
||||
if _, err := RecordHandActOnce(t.Context(), js.Conn(), HandAct{Verb: "warrant", Why: "x"}); err == nil {
|
||||
t.Fatal("an act without its id was written")
|
||||
}
|
||||
for i, want := range []bool{true, false, false} {
|
||||
written, err := RecordHandActOnce(t.Context(), js.Conn(), act)
|
||||
if err != nil || written != want {
|
||||
t.Fatalf("ask %d: written %v, %v", i, written, err)
|
||||
}
|
||||
}
|
||||
acts, err := HandActs(t.Context(), js.Conn(), time.Now().Add(-time.Hour))
|
||||
if err != nil || len(acts) != 1 || acts[0].ID != act.ID {
|
||||
t.Fatalf("%v %+v", err, acts)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user