The console reads the assigner's state assignments and imports the contracts' new paths (issue 1966)

Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
This commit is contained in:
2026-11-05 22:02:06 +01:00
parent bd555e6014
commit fb31cc4e99
16 changed files with 77 additions and 77 deletions
+20 -20
View File
@@ -17,8 +17,8 @@ package console
// session — so a tool that arrived a minute ago is found without the client reconnecting.
import (
assigner "git.novox.be/novox/mesh-contracts/placement/go/clients/meshmoduleassignerclient"
"git.novox.be/novox/mesh-contracts/placement/go/seats/meshmoduleassigner"
assigner "git.novox.be/novox/mesh-contracts/go/clients/meshmoduleassignerclient"
"git.novox.be/novox/mesh-contracts/go/seats/meshmoduleassigner"
meshcatalogclient "git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient"
"git.novox.be/novox/mesh-sdk/go/catalogue"
@@ -55,7 +55,7 @@ const (
// searchCap is how many matches a search answers before it says how many more there were.
const searchCap = 25
const grammar = "Addresses: `<seat>.<verb>` for a seat held once for the mesh (e.g. `mesh-module-assigner.placement`); " +
const grammar = "Addresses: `<seat>.<verb>` for a seat held once for the mesh (e.g. `mesh-module-assigner.assignments`); " +
"`<node>/<seat>.<verb>` for a seat every machine holds (e.g. `ace/node-packet-filter.rules`); " +
"`<node>/<module>.<tool>` for a module on one machine (e.g. `novox/postgres.postgres_list_databases`); " +
"and `<module>.<tool>` also for a module whose instances are interchangeable."
@@ -96,7 +96,7 @@ func discovery() []map[string]any {
"for when an address is said to be missing or on another machine."},
{"name": verbFirstViews, "inputSchema": obj(map[string]any{}),
"description": "The tool runner's first views of the four states it reads of the indexer and the assigner (the " +
"assigner's placement and seat-holders, the indexer's manifests and modules): for each, the owner, the tool " +
"assigner's assignments and seat-holders, the indexer's manifests and modules): for each, the owner, the tool " +
"asked, the revision held and when it was made, how many keys, when it was asked and answered, how often " +
"it was asked and how often by hand, whether its condition is raised, and why it was last asked. Read-only."},
{"name": verbFirstAgain, "inputSchema": obj(map[string]any{
@@ -145,7 +145,7 @@ type index struct {
NotAnswering []string
Listing *Listing // the flat catalogue the call path resolves subjects with
Discovery announce.Discovery
// Recorded is where placement places each module that declares tools.
// Recorded is where the assigner places each module that declares tools.
Recorded map[string][]string
// Unheard is every runtime whose answer this index lacks: it said it was there and did not say
// what it serves in time, or it answered before and not now. An address it might answer is never
@@ -245,7 +245,7 @@ func findTool(tools []Tool, name string) *Tool {
return nil
}
// recordedModule is a module as the bus holds it: where the placement seat places it, and whether its manifest declares
// recordedModule is a module as the bus holds it: where the assigner seat places it, and whether its manifest declares
// tools — what should announce itself, and where (novox/hq ADR 0571).
type recordedModule struct {
Module string `json:"module"`
@@ -271,9 +271,9 @@ func indexOn(conn *bus.Conn, src Source, held announce.Known, before func(announ
var recordsWhy []string
wg.Add(2)
// Which modules there are and where they are placed, and which machines the mesh has, from the bus (ADR 0571
// clauses 4 and 5): the indexer's modules and manifests and the placement seat's placements, never any other record.
// clauses 4 and 5): the indexer's modules and manifests and the assigner seat's assignments, never any other record.
go func() { defer wg.Done(); recorded, known, recordsWhy = recordsOn(src) }()
// Who holds which seat on which node, from placement (ADR 0571 clause 4): no other call.
// Who holds which seat on which node, from the assigner (ADR 0571 clause 4): no other call.
go func() { defer wg.Done(); placed, placedErr = seatHoldersOn(src) }()
d, err := announce.Gather(conn, held)
wg.Wait()
@@ -340,7 +340,7 @@ func indexOn(conn *bus.Conn, src Source, held announce.Known, before func(announ
}
l.NotAnswering = append(l.NotAnswering, recordsWhy...)
if x.PlacedWhy != "" {
l.NotAnswering = append(l.NotAnswering, firstview.SeatHoldersRead+" (who holds which seat by placement could not be read: "+
l.NotAnswering = append(l.NotAnswering, firstview.SeatHoldersRead+" (who holds which seat by assignment could not be read: "+
x.PlacedWhy+")")
}
for _, u := range x.Unheard {
@@ -360,7 +360,7 @@ func indexOn(conn *bus.Conn, src Source, held announce.Known, before func(announ
}
// Source is where the console reads the four states of the indexer and the assigner it indexes the mesh by: the assigner's
// placement and seat-holders, the indexer's modules and manifests, by `<owner>.<state>` (firstview.PlacementRead and the
// assignments and seat-holders, the indexer's modules and manifests, by `<owner>.<state>` (firstview.AssignmentsRead and the
// rest). The tool runner's is its first views (firstview.Views), never the owners' state (novox/hq ADR 0615 §1).
type Source interface {
// State is every current value of a state by key; an error says why it cannot be told yet.
@@ -390,21 +390,21 @@ type manifestFacts struct {
var manifestsKept sync.Map // digest → manifestFacts
// recordsOn is every module the indexer holds, with where the placement seat places it and whether it declares tools,
// and every machine placement names (moduleNames, assigner.MachineNames). What cannot be read is said, one line
// recordsOn is every module the indexer holds, with where the assigner seat places it and whether it declares tools,
// and every machine the assignments name (moduleNames, assigner.MachineNames). What cannot be read is said, one line
// per state, for the listing's not answering.
func recordsOn(src Source) (recorded []recordedModule, machines []string, why []string) {
placements, err := src.State(firstview.PlacementRead)
held, err := src.State(firstview.AssignmentsRead)
if err != nil {
why = append(why, firstview.PlacementRead+" (where modules are placed could not be read, so what is missing cannot "+
why = append(why, firstview.AssignmentsRead+" (where modules are placed could not be read, so what is missing cannot "+
"be said: "+err.Error()+")")
}
machines = assigner.MachineNames(placements)
machines = assigner.MachineNames(held)
on := map[string][]string{}
// The placement's keys in either form, a node key and its module keys or the form before (research 072 row 37).
assembled, err := assigner.PlacementsOf(placements)
// The assignments' keys in either form, a node key and its module keys or the form before (research 072 row 37).
assembled, err := assigner.AssignmentsOf(held)
if err != nil {
why = append(why, firstview.PlacementRead+" (not every key is a placement: "+err.Error()+")")
why = append(why, firstview.AssignmentsRead+" (not every key is an assignment: "+err.Error()+")")
}
for _, node := range machines {
for _, m := range assembled[node].Modules {
@@ -473,7 +473,7 @@ func manifestOf(src Source, digest string) (manifestFacts, error) {
return facts, nil
}
// placedHolders is who holds seat (on node, for a seat held per machine) by placement, or none.
// placedHolders is who holds seat (on node, for a seat held per machine) by assignment, or none.
func (x *index) placedHolders(seat, node string) []meshmoduleassigner.SeatHoldersHoldersItem {
if len(x.Placed) == 0 {
return nil
@@ -725,7 +725,7 @@ func resolve(x *index, address string) (target, error) {
for _, h := range hs {
held = append(held, h.Module+" on "+h.Node)
}
return target{}, fmt.Errorf("the seat %s is held by %s by placement, but no holder of it announced itself on the bus. "+
return target{}, fmt.Errorf("the seat %s is held by %s by assignment, but no holder of it announced itself on the bus. "+
"Ask again in a moment; mesh_runtimes shows which runtimes answered", prefix, strings.Join(held, ", "))
}
if len(x.Unheard) > 0 {