TLS-5, TLS-6: the views package is mesh-sdk's (go/views), and mesh_first_view_again is recorded through mesh-hand-acts before it is done (ADR 0615 §6, ADR 0565 §10, issue 1966)

Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
This commit is contained in:
2026-11-04 12:14:14 +01:00
parent 31247dff6b
commit d71cd5cef6
6 changed files with 40 additions and 8 deletions
-1
View File
@@ -8,7 +8,6 @@ require (
)
require (
git.novox.be/novox/mesh-delivery/sdk v0.0.0-00010101000000-000000000000
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261103221822-85ba0a9a70d8
github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op // indirect
github.com/google/go-tpm v0.9.8 // indirect
+24 -3
View File
@@ -2,10 +2,11 @@ package console
import (
"context"
"errors"
"log"
"strings"
"git.novox.be/novox/mesh-delivery/sdk/views"
"git.novox.be/novox/mesh-sdk/go/views"
)
// FirstViewer is the tool runner's four first views as the console shows them (novox/hq ADR 0615 §6; issue 1966 TLS-6): a
@@ -29,9 +30,14 @@ func (s *Surface) firstViewsAnswer(ctx context.Context, name string, args map[st
if why = strings.TrimSpace(why); why == "" {
why = "asked by hand with no reason given"
}
// A hand act, recorded in the runner's log with who asked and why (novox/hq ADR 0615 §6).
// A hand act, recorded through the seat mesh-hand-acts (novox/hq ADR 0615 §6, ADR 0565 §10) before it is done, and in the
// runner's log. One that cannot be recorded is said, and the ask is not made.
log.Printf("[mesh-tools] hand act: %s asked the four first views again: %s", s.who, why)
out := map[string]any{"asked again": why}
if err := s.recordAct(map[string]any{"what": "asked the tool runner's four first views again", "why": why,
"cause": "first-view-again", "verb": verbFirstAgain}); err != nil {
return failure("the hand act was not recorded through mesh-hand-acts, so the first views were not asked again: " + err.Error())
}
out := map[string]any{"asked again": why, "recorded": "mesh-hand-acts.hand-act"}
if errs := fv.Again(ctx, why); len(errs) > 0 {
var msgs []string
for _, e := range errs {
@@ -42,3 +48,18 @@ func (s *Surface) firstViewsAnswer(ctx context.Context, name string, args map[st
out["first views"] = fv.Status()
return answerText(out)
}
// recordAct records one act done by hand through the seat mesh-hand-acts (its verb hand-act); Surface.Record replaces the call
// in a test.
func (s *Surface) recordAct(args map[string]any) error {
if s.Record != nil {
return s.Record(args)
}
if s.conn == nil {
return errNoBus
}
_, err := s.conn.Ask("mesh-hand-acts.hand-act", args, "")
return err
}
var errNoBus = errors.New("no bus connection")
+12 -2
View File
@@ -3,10 +3,11 @@ package console
import (
"context"
"encoding/json"
"errors"
"strings"
"testing"
"git.novox.be/novox/mesh-delivery/sdk/views"
"git.novox.be/novox/mesh-sdk/go/views"
)
// viewer is a Source that also holds first views.
@@ -32,7 +33,8 @@ func TestTheConsoleShowsAndAsksAgainTheRunnersFirstViews(t *testing.T) {
return string(c)
}
v := &viewer{}
s := &Surface{src: v, who: "desk.node-tools"}
var recorded []map[string]any
s := &Surface{src: v, who: "desk.node-tools", Record: func(a map[string]any) error { recorded = append(recorded, a); return nil }}
if got := text(s.discover(context.Background(), "mesh_first_views", nil)); !strings.Contains(got, "mesh-delivery-assigner") || !strings.Contains(got, "placement") {
t.Errorf("mesh_first_views shows %s", got)
}
@@ -40,6 +42,14 @@ func TestTheConsoleShowsAndAsksAgainTheRunnersFirstViews(t *testing.T) {
if len(v.asked) != 1 || v.asked[0] != "doubted" || !strings.Contains(text(got), "asked again") {
t.Errorf("mesh_first_view_again asked %v and answered %s", v.asked, text(got))
}
if len(recorded) != 1 || recorded[0]["why"] != "doubted" || recorded[0]["cause"] != "first-view-again" {
t.Errorf("the hand act recorded is %v", recorded)
}
// An act that cannot be recorded is not done.
refusing := &Surface{src: v, who: "desk.node-tools", Record: func(map[string]any) error { return errors.New("no answer") }}
if r := refusing.discover(context.Background(), "mesh_first_view_again", map[string]any{"why": "x"}); r["isError"] != true || len(v.asked) != 1 {
t.Errorf("an unrecorded hand act was done: %s (asked %v)", text(r), v.asked)
}
for _, name := range []string{"mesh_first_views", "mesh_first_view_again"} {
none := &Surface{src: busSource{}, who: "desk.node-tools"}
if r := none.discover(context.Background(), name, nil); r["isError"] != true || !strings.Contains(text(r), "holds no first views") {
+2
View File
@@ -61,6 +61,8 @@ type Surface struct {
// Flat announces the whole catalogue, as the console did before ADR 0195: for a person reading
// it or a client that wants it. Off by default; MESH_CONSOLE_FLAT=1 turns it on.
Flat bool
// Record, when set, records a hand act in place of the seat mesh-hand-acts' verb (a test's).
Record func(args map[string]any) error
}
// MethodSeats is the console's JSON-RPC method beside MCP's that answers every seat's verbs and holders, in the shape
+1 -1
View File
@@ -15,7 +15,7 @@ import (
"sync"
"time"
"git.novox.be/novox/mesh-delivery/sdk/views"
"git.novox.be/novox/mesh-sdk/go/views"
"github.com/novox/mesh-tools/node-tools/internal/bus"
)
@@ -9,7 +9,7 @@ import (
"testing"
"time"
"git.novox.be/novox/mesh-delivery/sdk/views"
"git.novox.be/novox/mesh-sdk/go/views"
"github.com/novox/mesh-tools/node-tools/internal/bus"
)