Take the catalogue's composition rules into the node-engine

ADR 0593 §7: the composer with its refusals leaves mesh-sdk, so mesh-sdk
carries no composition rule. The catalogue functions only the
node-engine's composition reaches (Resolve, Resolution's Compose,
Declaration, DataItems, LeftOut, Rules and the rest, the settings,
placeholder and template refusals, the rendering helpers) are copied
with their tests into internal/compose/resolution; a method of a
mesh-sdk shape becomes a function taking it first. The composition
calls its own copies, and the captured catalogue its tests read lives
here now, shared by mesh-compose's tests.

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
This commit is contained in:
2026-11-02 19:15:55 +01:00
parent be0226b624
commit d68e241724
686 changed files with 35703 additions and 80 deletions
+8 -7
View File
@@ -8,6 +8,7 @@ import (
"strings"
"git.novox.be/novox/mesh-sdk/go/catalogue"
"github.com/novox/mesh-host/internal/compose/resolution"
)
// notResolvable marks the one failure in a node's resolution that is a statement about the node: its assigned modules
@@ -120,7 +121,7 @@ func (c *composer) theRestOfTheMeshNow(exclude string) (catalogue.World, Passes,
var firstHeld []catalogue.Held
c.unhostable = nil
for _, o := range others {
got, err := catalogue.Resolve(shelf, o.assigned, o.node, catalogue.World{Unchecked: true, Holdings: holdings})
got, err := resolution.Resolve(shelf, o.assigned, o.node, catalogue.World{Unchecked: true, Holdings: holdings})
if err != nil {
// Said, not skipped: a machine dropped here offers nothing and holds nothing.
left = append(left, LeftOut{Node: o.node.Name, Err: err})
@@ -138,7 +139,7 @@ func (c *composer) theRestOfTheMeshNow(exclude string) (catalogue.World, Passes,
return catalogue.World{}, Passes{}, nil, err
}
// And its own composed names, as that node composes them (novox/hq ADR 0346).
serves, leftOut, err := got.ServedOwnNames(m, name, serves, catalogue.WithDefaults(m, layers))
serves, leftOut, err := resolution.ServedOwnNames(got, m, name, serves, resolution.WithDefaults(m, layers))
if err != nil {
return catalogue.World{}, Passes{}, nil, err
}
@@ -160,7 +161,7 @@ func (c *composer) theRestOfTheMeshNow(exclude string) (catalogue.World, Passes,
// Each machine is resolved with its own pins, as its plan is.
theirs := world
theirs.Pinned = o.pins
got, err := catalogue.Resolve(shelf, o.assigned, o.node, theirs)
got, err := resolution.Resolve(shelf, o.assigned, o.node, theirs)
if err != nil {
// Said only for the whole-mesh view: with one machine excluded, the view is partial by design.
if exclude == "" {
@@ -178,7 +179,7 @@ func (c *composer) theRestOfTheMeshNow(exclude string) (catalogue.World, Passes,
// assigned nowhere and which has exactly one claimant able to hold it (novox/hq ADR 0449 clause 4), and answers the
// holdings as they are after it, with the passes. Nothing is recorded.
func passSeatsOn(holdings []catalogue.Held, assignments []catalogue.Assignment) ([]catalogue.Held, Passes) {
passes, said := catalogue.SeatsToPassOn(holdings, assignments)
passes, said := resolution.SeatsToPassOn(holdings, assignments)
out := Passes{Said: said}
for _, p := range passes {
out.Passes = append(out.Passes, p)
@@ -224,9 +225,9 @@ func (c *composer) servedOnNode(node string, m catalogue.Manifest, provision str
if err != nil {
return nil, nil, err
}
serves := catalogue.ServedOn(m, provision, ports)
serves := resolution.ServedOn(m, provision, ports)
if len(serves) > 0 {
serves, err = catalogue.Settle(serves, catalogue.WithDefaults(m, layers))
serves, err = resolution.Settle(serves, resolution.WithDefaults(m, layers))
if err != nil {
return nil, nil, err
}
@@ -246,7 +247,7 @@ func (c *composer) portsGivenOn(node string, m catalogue.Manifest) (map[int]int,
ports[wanted] = at
}
layers := n.Settings[m.Module]
if given, err := catalogue.GivenPorts(m, layers); err == nil {
if given, err := resolution.GivenPorts(m, layers); err == nil {
for wanted, at := range given {
ports[wanted] = at
}