Record a module's act on the operator's warrant from the router's own record (hq ADR 0274)
A module that asks the operator acts with its own grants, and the hand-act log is where a person's decisions are read back. The new verb warranted records who chose, how and with which proofs from the router's record, never the caller's word, once per ask however many instances ask.
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"git.novox.be/novox/mesh-sdk/go/asks"
|
||||
|
||||
"github.com/novox/mesh-controller/internal/conditions"
|
||||
)
|
||||
|
||||
func chosenWarrant() *asks.Warrant {
|
||||
return &asks.Warrant{Ask: "instr-1", Asker: "claude-code", Outcome: asks.OutcomeChosen, Option: "approve",
|
||||
Label: "Approve", Level: asks.Approve, Channel: "telegram", Proofs: []string{"P1"},
|
||||
By: &asks.Person{Who: asks.Operator, Kind: "telegram", Identity: "42", Verified: "user id verified"},
|
||||
At: time.Date(2026, 10, 10, 4, 0, 0, 0, time.UTC), AskDigest: "sha256:ab"}
|
||||
}
|
||||
|
||||
// What is recorded of a module's act on a warrant is the router's word (novox/hq ADR 0274): who chose, how and
|
||||
// with which proofs; the caller gives only what it did. Nothing is recorded without a person's choice.
|
||||
func TestAWarrantIsRecordedFromTheRoutersRecordAlone(t *testing.T) {
|
||||
act, err := warrantedAct("claude-code", "instr-1", "claude-code proposal instr-1 approved on shanks",
|
||||
"node-tools.shanks", "chosen", chosenWarrant())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if act.ID != "warrant-claude-code-instr-1" || act.Verb != handActWarrant || act.Cause != conditions.CauseOperatorAnswer ||
|
||||
act.By != "the operator, as telegram identity 42" || act.Ask != "instr-1" || !slices.Equal(act.Proofs, []string{"P1"}) ||
|
||||
!strings.Contains(act.Why, "the operator, via telegram (user id verified), chose Approve") ||
|
||||
!strings.Contains(act.RequestedBy, "node-tools.shanks") {
|
||||
t.Fatalf("recorded as %+v", act)
|
||||
}
|
||||
for name, c := range map[string]struct {
|
||||
asker, ask, state string
|
||||
w func() *asks.Warrant
|
||||
}{
|
||||
"no record": {"claude-code", "instr-1", "", func() *asks.Warrant { return nil }},
|
||||
"still open": {"claude-code", "instr-1", "open", chosenWarrant},
|
||||
"another asker's": {"messenger", "instr-1", "chosen", chosenWarrant},
|
||||
"another ask's": {"claude-code", "instr-2", "chosen", chosenWarrant},
|
||||
"the controller's": {"mesh-controller", "instr-1", "chosen", chosenWarrant},
|
||||
"not a module": {"Claude Code", "instr-1", "chosen", chosenWarrant},
|
||||
"expired": {"claude-code", "instr-1", "expired", func() *asks.Warrant {
|
||||
w := chosenWarrant()
|
||||
w.Outcome, w.By = asks.OutcomeExpired, nil
|
||||
return w
|
||||
}},
|
||||
"no digest": {"claude-code", "instr-1", "chosen", func() *asks.Warrant {
|
||||
w := chosenWarrant()
|
||||
w.AskDigest = ""
|
||||
return w
|
||||
}},
|
||||
} {
|
||||
if _, err := warrantedAct(c.asker, c.ask, "did it", "x", c.state, c.w()); err == nil {
|
||||
t.Errorf("%s: recorded", name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestTheWarrantedVerbRunsTheWarrantLineWithoutAWhy(t *testing.T) {
|
||||
argv, err := argvFor("warranted", map[string]any{"asker": "claude-code", "ask": "instr-1", "what": "approved on shanks"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !slices.Equal(argv, []string{"hand-act", "warrant", "--asker", "claude-code", "--ask", "instr-1", "approved on shanks"}) {
|
||||
t.Fatalf("%v", argv)
|
||||
}
|
||||
if repairingCommand(argv) != "" {
|
||||
t.Error("recording a person's answer is taken for a repair")
|
||||
}
|
||||
if terminalOnly(argv) != nil {
|
||||
t.Error("the verb is kept for the terminal")
|
||||
}
|
||||
if _, err := argvFor("warranted", map[string]any{"asker": "claude-code"}); err == nil {
|
||||
t.Error("a call naming no ask was taken")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user