The indexer claims the seat mesh-catalog and its tools bundle serves the four verbs from its states (ADR 0604 §2, issue 774)
CatalogTools moves into the index package so its row sits in the existing catalog test. Claude-Session: https://claude.ai/code/session_01JG73KG7AfSdh6FP8VrBqCn
This commit is contained in:
@@ -4,7 +4,6 @@ import (
|
||||
"fmt"
|
||||
|
||||
stdio "git.novox.be/novox/mesh-sdk/go"
|
||||
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
||||
"git.novox.be/novox/mesh-sdk/go/delivery"
|
||||
|
||||
"git.novox.be/novox/mesh-delivery/sdk/graph"
|
||||
@@ -12,30 +11,6 @@ import (
|
||||
"mesh-delivery-indexer/internal/index"
|
||||
)
|
||||
|
||||
// CatalogTools are the seat mesh-catalog's four verbs as tools named <seat>.<verb>, with the descriptions and inputs the
|
||||
// seat's contract gives them (novox/hq ADR 0604 §1, §2), answered from the indexer's own states. They are served once the
|
||||
// indexer's manifest claims the seat, in the release after L3's (the lead's decision): until then main serves them not.
|
||||
func CatalogTools(c index.CatalogRead) []stdio.Tool {
|
||||
seat, ok := catalogue.SeatNamed(catalogue.CatalogSeat)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
str := func(args map[string]any, k string) string { s, _ := args[k].(string); return s }
|
||||
runs := map[string]func(map[string]any) (any, error){
|
||||
"modules": func(map[string]any) (any, error) { return c.CatalogModulesAnswer() },
|
||||
"module": func(a map[string]any) (any, error) { return c.CatalogModuleAnswer(str(a, "module")) },
|
||||
"provides": func(a map[string]any) (any, error) { return c.CatalogProvidesAnswer(str(a, "provision")) },
|
||||
"dependents": func(a map[string]any) (any, error) { return c.CatalogDependentsAnswer(str(a, "module")) },
|
||||
}
|
||||
var out []stdio.Tool
|
||||
for _, v := range seat.Serves {
|
||||
if run, ok := runs[v.Name]; ok {
|
||||
out = append(out, stdio.Tool{Name: catalogue.CatalogSeat + "." + v.Name, Description: v.Description, Input: v.Input, Run: run})
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// catalogRead reads the indexer's modules, manifests and graph states for the seat's verbs.
|
||||
func catalogRead(modules, manifests, nodes stdio.KeptState) index.CatalogRead {
|
||||
return index.CatalogRead{
|
||||
@@ -97,7 +72,7 @@ func catalogRead(modules, manifests, nodes stdio.KeptState) index.CatalogRead {
|
||||
}
|
||||
}
|
||||
|
||||
// catalogTools are the seat's verbs over the indexer's own states, as main serves them once the indexer claims the seat.
|
||||
// catalogTools are the seat's verbs over the indexer's own states, served beside the indexer's own tools, since the indexer's manifest claims the seat (ADR 0604 §2).
|
||||
func catalogTools() []stdio.Tool {
|
||||
return CatalogTools(catalogRead(stdio.State("modules"), stdio.State("manifests"), stdio.State(graph.State)))
|
||||
return index.CatalogTools(catalogRead(stdio.State("modules"), stdio.State("manifests"), stdio.State(graph.State)))
|
||||
}
|
||||
|
||||
@@ -190,7 +190,7 @@ func heldCounts(s stdio.KeptState) func() (index.OldSectionsCount, error) {
|
||||
}
|
||||
|
||||
func main() {
|
||||
if err := stdio.Serve("", Tools(askTakeIn(stdio.State(index.TakeInsState), 25*time.Second), time.Now, stdio.State(index.VerdictsState), heldCounts(stdio.State(index.OldSectionsState)))); err != nil {
|
||||
if err := stdio.Serve("", append(Tools(askTakeIn(stdio.State(index.TakeInsState), 25*time.Second), time.Now, stdio.State(index.VerdictsState), heldCounts(stdio.State(index.OldSectionsState))), catalogTools()...)); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "[mesh-delivery-indexer-tools] %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
stdio "git.novox.be/novox/mesh-sdk/go"
|
||||
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
||||
"git.novox.be/novox/mesh-sdk/go/delivery"
|
||||
|
||||
@@ -147,3 +148,27 @@ func (c CatalogRead) graphAndModules() (graph.Graph, map[string]delivery.Module,
|
||||
}
|
||||
return g, mods, nil
|
||||
}
|
||||
|
||||
// CatalogTools are the seat mesh-catalog's four verbs as tools named <seat>.<verb>, with the descriptions and inputs the
|
||||
// seat's contract gives them (novox/hq ADR 0604 §1, §2), answered from the indexer's own states. They are served once the
|
||||
// indexer's manifest claims the seat, in the release after L3's (the lead's decision): until then main serves them not.
|
||||
func CatalogTools(c CatalogRead) []stdio.Tool {
|
||||
seat, ok := catalogue.SeatNamed(catalogue.CatalogSeat)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
str := func(args map[string]any, k string) string { s, _ := args[k].(string); return s }
|
||||
runs := map[string]func(map[string]any) (any, error){
|
||||
"modules": func(map[string]any) (any, error) { return c.CatalogModulesAnswer() },
|
||||
"module": func(a map[string]any) (any, error) { return c.CatalogModuleAnswer(str(a, "module")) },
|
||||
"provides": func(a map[string]any) (any, error) { return c.CatalogProvidesAnswer(str(a, "provision")) },
|
||||
"dependents": func(a map[string]any) (any, error) { return c.CatalogDependentsAnswer(str(a, "module")) },
|
||||
}
|
||||
var out []stdio.Tool
|
||||
for _, v := range seat.Serves {
|
||||
if run, ok := runs[v.Name]; ok {
|
||||
out = append(out, stdio.Tool{Name: catalogue.CatalogSeat + "." + v.Name, Description: v.Description, Input: v.Input, Run: run})
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
@@ -93,6 +93,19 @@ func catalogVerbsAnswerFromTheStates(t *testing.T) {
|
||||
}
|
||||
return true
|
||||
}
|
||||
// The tools bundle serves the four verbs as mesh-catalog.<verb>, answering from the same states.
|
||||
var names []string
|
||||
for _, tool := range CatalogTools(c) {
|
||||
names = append(names, tool.Name)
|
||||
if tool.Name == "mesh-catalog.modules" {
|
||||
if got, err := tool.Run(nil); err != nil || !strings.Contains(string(answer(got, nil)), `"module":"avahi"`) {
|
||||
t.Errorf("mesh-catalog.modules answered %v, %v", got, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
if !slices.Equal(names, []string{"mesh-catalog.modules", "mesh-catalog.module", "mesh-catalog.provides", "mesh-catalog.dependents"}) {
|
||||
t.Errorf("the tools bundle serves %v", names)
|
||||
}
|
||||
raw := answer(c.CatalogModulesAnswer())
|
||||
if got, want := keysAt(t, raw, "modules"), capturedKeys(t, "catalog_modules.json", "modules"); !contains(got, want) {
|
||||
t.Errorf("modules' fields %v, want the old catalog's %v", got, want)
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
||||
"git.novox.be/novox/mesh-sdk/go/delivery"
|
||||
|
||||
"git.novox.be/novox/mesh-delivery/sdk/graph"
|
||||
@@ -38,9 +39,14 @@ type artifact struct {
|
||||
}
|
||||
|
||||
type manifest struct {
|
||||
Module string `json:"module"`
|
||||
Version string `json:"version"`
|
||||
Slug string `json:"slug"`
|
||||
Module string `json:"module"`
|
||||
Version string `json:"version"`
|
||||
Slug string `json:"slug"`
|
||||
Claims []struct {
|
||||
Name string `json:"name"`
|
||||
Scope string `json:"scope"`
|
||||
Serves []string `json:"serves"`
|
||||
} `json:"claims"`
|
||||
Tools []string `json:"tools"`
|
||||
Emits []string `json:"emits"`
|
||||
Consumes []string `json:"consumes"`
|
||||
@@ -122,8 +128,14 @@ func TestManifestDeclarations(t *testing.T) { // 1238/AC1, 1444 (reads the build
|
||||
if want := []string{"indexer_take_in", "indexer_old_sections", "indexer_verdicts", "indexer_judge"}; !reflect.DeepEqual(m.Tools, want) {
|
||||
t.Errorf("tools = %v, want %v", m.Tools, want)
|
||||
}
|
||||
// No streams, no bus, no seat (ADR 0437 §4); it says no event.
|
||||
for _, k := range []string{"streams", "logs", "claims", "provides", "requires", "uses", "defines-seats", "seat", "seats", "bus"} {
|
||||
// ADR 0604 §2: it holds the seat mesh-catalog, serving its four verbs from its tools bundle (which stays without a
|
||||
// request subject).
|
||||
if len(m.Claims) != 1 || m.Claims[0].Name != catalogue.CatalogSeat || m.Claims[0].Scope != catalogue.ScopeMesh ||
|
||||
!slices.Equal(m.Claims[0].Serves, []string{"modules", "module", "provides", "dependents"}) {
|
||||
t.Errorf("claims = %+v, want mesh-catalog with its four verbs", m.Claims)
|
||||
}
|
||||
// No streams, no bus, no other seat (ADR 0437 §4); it says no event.
|
||||
for _, k := range []string{"streams", "logs", "provides", "requires", "uses", "defines-seats", "seat", "seats", "bus"} {
|
||||
if _, ok := top[k]; ok {
|
||||
t.Errorf("the manifest declares %q: the indexer has none", k)
|
||||
}
|
||||
|
||||
@@ -2,6 +2,18 @@
|
||||
"module": "mesh-delivery-indexer",
|
||||
"version": "1",
|
||||
"slug": "indexer",
|
||||
"claims": [
|
||||
{
|
||||
"name": "mesh-catalog",
|
||||
"scope": "mesh",
|
||||
"serves": [
|
||||
"modules",
|
||||
"module",
|
||||
"provides",
|
||||
"dependents"
|
||||
]
|
||||
}
|
||||
],
|
||||
"tools": [
|
||||
"indexer_take_in",
|
||||
"indexer_old_sections",
|
||||
|
||||
Reference in New Issue
Block a user