claude-code: the seat list is read from the seat mesh-catalog and followed on its events, the hand acts go through the hand-acts client, the seat is mesh-module-assigner (K-23, K-21 part, K-4..K-20 part; ADR 0635 §1, ADR 0634 §9; issue 1966)

This commit is contained in:
2026-11-05 14:14:32 +01:00
parent 7ae2ed88c0
commit 2f7ff1c911
10 changed files with 175 additions and 43 deletions
+25 -4
View File
@@ -23,11 +23,10 @@ import (
"time"
occ "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/clients/operatorchannelclient"
"git.novox.be/novox/mesh-contracts/go/seats"
oc "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/seats/operatorchannel"
stdio "git.novox.be/novox/mesh-sdk/go"
"git.novox.be/novox/mesh-sdk/go/delivery"
"git.novox.be/novox/mesh-sdk/go/handacts"
"git.novox.be/novox/mesh-sdk/go/seatlist"
"git.novox.be/novox/mesh-sdk/go/views"
)
@@ -230,7 +229,7 @@ var meshChanged = make(chan struct{}, 1)
// newMeshViews builds the reader of those three states; Start asks them.
func newMeshViews() *views.Reader {
v := &views.Reader{Module: Module, Logf: func(f string, a ...any) { say(f, a...) }, Findings: views.OwnFindings{},
Acts: handacts.Recorder{Ask: stdio.Ask},
Acts: handActs{},
Changed: func(string, string, json.RawMessage, bool) {
select {
case meshChanged <- struct{}{}:
@@ -319,7 +318,7 @@ func tools(p Paths, servers ServerState, view *ServerView, config ConfigState, c
Description: "Write Claude Code's managed directory now, from the mesh's facts, this module's settings and the servers registered here — after reading the bus again for what each tool replaces and which machines the mesh has (the instructions' table and the shell's guard).",
Run: func(map[string]any) (any, error) {
answer := map[string]any{}
if m, err := ReadMeshToolsFrom(viewStates{meshViews}, seats.List(), lookup); err != nil {
if m, err := ReadMeshToolsFrom(viewStates{meshViews}, definedSeats(), lookup); err != nil {
answer["asked"] = "the bus could not be read in full (" + err.Error() + "); what was kept is rendered"
} else {
KeepMeshTools(p, m)
@@ -406,6 +405,7 @@ func tools(p Paths, servers ServerState, view *ServerView, config ConfigState, c
}
out = append(out, judgeTool(judge), judgedTool(judge))
out = append(out, meshViews.Tools("claude_code")...)
out = append(out, seatListTools()...)
return append(out, configTools(p, config, configView)...)
}
@@ -659,3 +659,24 @@ func refusals(n int) string {
}
return fmt.Sprintf(" (after %d refusal(s))", n)
}
// seatListTools are the seat list reader's two tools: what the list holds and what it waits for, and a read now. The
// reader starts once the runtime serves, after the tools are listed, so each tool finds it when it is called.
func seatListTools() []stdio.Tool {
names := []string{"claude_code_seat_list", "claude_code_seat_list_again"}
callers := stdio.Callers{"mesh-healers"}
shape := seatlist.Tools(&seatlist.Reader{}, names[0], names[1], callers)
for i := range shape {
run := i
shape[i].Run = func(args map[string]any) (any, error) {
seatListMu.Lock()
r := seatList
seatListMu.Unlock()
if r == nil {
return nil, errors.New("the seat list reader has not started yet: the runtime has not served this module")
}
return seatlist.Tools(r, names[0], names[1], callers)[run].Run(args)
}
}
return shape
}