seatlist: the again tool answers a VerbCallers-style list, so the operator's sessions can be named (ADR 0636 §7; issue 1966)

Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
This commit is contained in:
2026-11-05 14:31:27 +01:00
parent a0480588ce
commit e0d2298f58
2 changed files with 10 additions and 9 deletions
+8 -7
View File
@@ -383,7 +383,7 @@ func (r *Reader) changed() {
// (every definition, its source and digest) and what it waits for; and again, which makes it read the list now, and
// answers only to the callers the host's list names (the operator and the healers). The host names the tools and the list;
// again records nothing but the read it asked.
func Tools(r *Reader, read, again string, callers stdio.Callers) []stdio.Tool {
func Tools(r *Reader, read, again string, callers []string) []stdio.Tool {
return []stdio.Tool{
{Name: read,
Description: "The seat list this part holds (novox/hq ADR 0636): each seat's definition with its source (trunk or bootstrap) and " +
@@ -412,11 +412,12 @@ func Tools(r *Reader, read, again string, callers stdio.Callers) []stdio.Tool {
}
}
// Refusal is why caller may not make the reader read again, or nil: the caller's proof, never an argument, against the
// list of the operator and the healers.
func Refusal(tool string, callers stdio.Callers, caller string) error {
if callers.Allows(caller) {
return nil
// Refusal is why caller may not make the reader read again, or nil: the caller's proof, never an argument, against
// callers, the entries of a verb's list as VerbCallers reads them, so stdio.AnyPerson names every operator's session
// the runtime proved (person.<name>) and a module name its instances (ADR 0636 §7).
func Refusal(tool string, callers []string, caller string) error {
if err := (stdio.VerbCallers{tool: callers}).Allowed(tool, caller); err != nil {
return fmt.Errorf("%s is refused to %q: it answers only %s (novox/hq ADR 0636 §7)", tool, caller, strings.Join(callers, ", "))
}
return fmt.Errorf("%s is refused to %q: it answers only %s (novox/hq ADR 0636 §7)", tool, caller, strings.Join(callers, ", "))
return nil
}
+2 -2
View File
@@ -199,13 +199,13 @@ func TestTheTwoToolsReadTheHeldListAndReadItAgainForTheirCallers(t *testing.T) {
if err != nil {
t.Fatal(err)
}
callers := stdio.Callers{"person.jo", "mesh-healers"}
callers := []string{stdio.AnyPerson, "mesh-healers"}
tools := Tools(r, "seat_list", "seat_list_again", callers)
out, err := tools[0].Run(map[string]any{})
if err != nil || out.(map[string]any)["health"] == "" || !strings.Contains(fmt.Sprint(out.(map[string]any)["status"]), "bootstrap") {
t.Fatalf("read: %v %v", out, err)
}
for caller, allowed := range map[string]bool{"person.jo": true, "ace.mesh-healers": true, "ace.mesh-other": false, "person.al": false, stdio.Unproven: false} {
for caller, allowed := range map[string]bool{"person.jo": true, "ace.mesh-healers": true, "ace.mesh-other": false, "person.al": true, stdio.Unproven: false} {
if err := Refusal("seat_list_again", callers, caller); (err == nil) != allowed {
t.Fatalf("%s: %v, allowed %v", caller, err, allowed)
}