Files
mesh-catalog/modules/mesh-config/cmd/mesh-config/switch_tools.go
T
jschoubben 376a8b0fb5 CAT-C1..C8, C10: mesh-config moves a renamed config value, answers both names in the rename window, retires an unread value on the operator's Approve; the keeper reads its findings
A declaration's renamed-from moves the value with its trust and opens a window per node,
closed on delivered and, for a returning node-engine, on manifest-reads-changed (ADR 0618).
A value no manifest reads is marked retiring only once no node runs a build that reads it,
asked once, removed only on the Approve (a secret through the seat mesh-vault's retire).
New state in the old sections (ADR 0619), the stream config-events, the tools config_renames,
config_rename_again, config_rename_close, config_retiring and the seat verb renames.

Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
2026-11-04 11:46:16 +01:00

89 lines
4.5 KiB
Go

package main
// The module's own tools beside the seat's verb (novox/hq ADR 0565 §15): the read of `declared` and resync. compare,
// take-over and hand-back went with the controller (ADR 0590).
import (
"strings"
stdio "git.novox.be/novox/mesh-sdk/go"
)
// The switch's tools.
const (
DeclaredTool = "config_declared"
ResyncTool = "config_resync"
RenamesTool = "config_renames"
RenameAgainTool = "config_rename_again"
RenameCloseTool = "config_rename_close"
RetiringTool = "config_retiring"
RenamesVerb = "renames"
)
// SeatVerbs are the seat's verbs, as the manifest claims them: `config`, and the optional `renames` the checker asks
// (design 32: the open renames and the nodes holding each window open).
var SeatVerbs = []string{Verb, RenamesVerb}
func switchTools(c *Config) []stdio.Tool { return ownSwitchTools(c) }
func ownSwitchTools(c *Config) []stdio.Tool {
return []stdio.Tool{
{Name: DeclaredTool,
Description: "Each placed module's declarations as config keeps them (its state declared): the manifest and " +
"commit they come from and how many keys, or one module whole; and which source holds now.",
Input: map[string]any{"type": "object", "properties": map[string]any{
"module": map[string]any{"type": "string", "description": "one module, whole"}}},
Run: func(a map[string]any) (any, error) {
m, _ := a["module"].(string)
return c.Declared(strings.TrimSpace(m))
}},
{Name: ResyncTool,
Description: "Read every source again and write what differs: the published list of predefined keys, the " +
"resolved values, declared, and the indexer's config candidates.",
Run: func(map[string]any) (any, error) { return c.Resync() }},
{Name: RenamesTool,
Description: "Each config value renamed (renamed-from): from which name to which, when, the nodes its value " +
"moved on, the nodes still holding the old name open (the rename window) and how each closed one closed. " +
"Narrowed by module.",
Input: map[string]any{"type": "object", "properties": map[string]any{
"module": map[string]any{"type": "string", "description": "one module"}}},
Run: func(a map[string]any) (any, error) {
m, _ := a["module"].(string)
rows, err := c.Renames(strings.TrimSpace(m), false)
return map[string]any{"renames": rows}, err
}},
{Name: RenameAgainTool,
Description: "Move a renamed value by hand, the way a resolution does: after a refused move (its finding says " +
"why) once the cause is put right, or for a value set under the old name meanwhile.",
Input: map[string]any{"type": "object", "required": []string{"module", "to"}, "properties": map[string]any{
"module": map[string]any{"type": "string"}, "to": map[string]any{"type": "string", "description": "the new name"}}},
Run: func(a map[string]any) (any, error) {
m, _ := a["module"].(string)
to, _ := a["to"].(string)
return c.RenameAgain(strings.TrimSpace(m), strings.TrimSpace(to))
}},
{Name: RenameCloseTool,
Description: "Drop a node from a rename's window by hand (a node retired for good), recorded as a hand act: " +
"the old name is no longer answered for it.",
Input: map[string]any{"type": "object", "required": []string{"module", "to", "node", "why"}, "properties": map[string]any{
"module": map[string]any{"type": "string"}, "to": map[string]any{"type": "string", "description": "the new name"},
"node": map[string]any{"type": "string"}, "why": map[string]any{"type": "string"}}},
Run: func(a map[string]any) (any, error) {
str := func(k string) string { v, _ := a[k].(string); return strings.TrimSpace(v) }
return c.RenameClose(str("module"), str("to"), str("node"), str("why"))
}},
{Name: RetiringTool,
Description: "The config values and secrets no manifest reads any more: since when, where each stands (draining " +
"while a node still runs a build that reads it, asked, unanswered, approved, declined) and its ask. With " +
"action ask-again, ask the operator once more about one; with cancel, drop one (it is asked about no more " +
"until it is read again).",
Input: map[string]any{"type": "object", "properties": map[string]any{
"action": map[string]any{"type": "string", "enum": []string{"list", "ask-again", "cancel"}},
"module": map[string]any{"type": "string"}, "key": map[string]any{"type": "string"}}},
Run: func(a map[string]any) (any, error) {
str := func(k string) string { v, _ := a[k].(string); return strings.TrimSpace(v) }
return c.ConfigRetiring(str("action"), str("module"), str("key"))
}},
}
}