CAT-CC3: claude-code reads the indexer's modules and manifests and the assigner's placement from their first views and views events, never their state (ADR 0615 §1)
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
This commit is contained in:
@@ -12,6 +12,7 @@ package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
@@ -24,6 +25,9 @@ import (
|
||||
"git.novox.be/novox/mesh-contracts/go/seats"
|
||||
stdio "git.novox.be/novox/mesh-sdk/go"
|
||||
"git.novox.be/novox/mesh-sdk/go/asks"
|
||||
"git.novox.be/novox/mesh-sdk/go/delivery"
|
||||
"git.novox.be/novox/mesh-sdk/go/handacts"
|
||||
"git.novox.be/novox/mesh-sdk/go/views"
|
||||
)
|
||||
|
||||
func say(format string, args ...any) {
|
||||
@@ -205,23 +209,46 @@ func (s stateOf) Get(key string) (json.RawMessage, bool, error) {
|
||||
return e.Value, true, nil
|
||||
}
|
||||
|
||||
// nodesRunningMe is the nodes claude-code runs on, from the seat mesh-placement's placement — for the register
|
||||
// tool's question.
|
||||
func nodesRunningMe() ([]string, error) { return NodesRunning(busStates{}, "claude-code") }
|
||||
// nodesRunningMe is the nodes claude-code runs on, from the assigner's placement — for the register tool's question.
|
||||
func nodesRunningMe() ([]string, error) { return NodesRunning(viewStates{meshViews}, "claude-code") }
|
||||
|
||||
// busStates reads the states the manifest declares in its reads through the runtime.
|
||||
type busStates struct{}
|
||||
// The owners' read tools of the states this module follows, which the manifest invokes (novox/hq ADR 0615 §1).
|
||||
const (
|
||||
ModulesTool = delivery.IndexerModule + ".indexer_read_modules"
|
||||
ManifestsTool = delivery.IndexerModule + ".indexer_read_manifests"
|
||||
PlacementTool = delivery.AssignerModule + ".assigner_read_placement"
|
||||
)
|
||||
|
||||
func (busStates) Keys(read string) ([]string, error) { return stdio.State(read).Keys() }
|
||||
// meshViews is this module's picture of the indexer's modules and manifests and the assigner's placement: each asked
|
||||
// once of the owner's read tool, then followed on the owner's views family. It reads none of their state.
|
||||
var meshViews *views.Reader
|
||||
|
||||
func (busStates) Get(read, key string) ([]byte, bool, error) {
|
||||
e, err := stdio.State(read).Get(key)
|
||||
if err != nil || e == nil {
|
||||
return nil, false, err
|
||||
}
|
||||
return e.Value, true, nil
|
||||
// meshChanged is told, without waiting, that a followed state changed: the instructions' table is read again.
|
||||
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},
|
||||
Changed: func(string, string, json.RawMessage, bool) {
|
||||
select {
|
||||
case meshChanged <- struct{}{}:
|
||||
default:
|
||||
}
|
||||
}}
|
||||
v.Follow(delivery.IndexerModule, "modules", ModulesTool)
|
||||
v.Follow(delivery.IndexerModule, "manifests", ManifestsTool)
|
||||
v.Follow(delivery.AssignerModule, "placement", PlacementTool)
|
||||
return v
|
||||
}
|
||||
|
||||
// viewStates reads the followed states from the reader's pictures, never from the owners' state.
|
||||
type viewStates struct{ v *views.Reader }
|
||||
|
||||
func (s viewStates) Keys(read string) ([]string, error) { return s.v.Keys(read) }
|
||||
|
||||
func (s viewStates) Get(read, key string) ([]byte, bool, error) { return s.v.Get(read, key) }
|
||||
|
||||
func fingerprintOfFile(path string) any {
|
||||
raw, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
@@ -291,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(busStates{}, seats.List(), lookup); err != nil {
|
||||
if m, err := ReadMeshToolsFrom(viewStates{meshViews}, seats.List(), lookup); err != nil {
|
||||
answer["asked"] = "the bus could not be read in full (" + err.Error() + "); what was kept is rendered"
|
||||
} else {
|
||||
KeepMeshTools(p, m)
|
||||
@@ -377,6 +404,7 @@ func tools(p Paths, servers ServerState, view *ServerView, config ConfigState, c
|
||||
return stdio.Emit("judged", e, stdio.EmitOptions{MessageID: id})
|
||||
}
|
||||
out = append(out, judgeTool(judge), judgedTool(judge))
|
||||
out = append(out, meshViews.Tools("claude_code")...)
|
||||
return append(out, configTools(p, config, configView)...)
|
||||
}
|
||||
|
||||
@@ -422,6 +450,7 @@ func main() {
|
||||
return
|
||||
}
|
||||
p, launched := PathsFrom(os.Getenv)
|
||||
meshViews = newMeshViews()
|
||||
if launched {
|
||||
fsys = FilesFor(p)
|
||||
}
|
||||
@@ -451,6 +480,7 @@ func main() {
|
||||
}
|
||||
}
|
||||
}
|
||||
meshViews.Start(context.Background())
|
||||
go refreshMeshTools(p)
|
||||
servers := stateOf{stdio.State("servers")}
|
||||
view := NewServerView(p)
|
||||
|
||||
Reference in New Issue
Block a user