Keep the filled paths of the modules moved into a node's own composition, which the node-engine otherwise wrote empty (issue 1945)
This commit is contained in:
@@ -7,6 +7,10 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"encoding/json"
|
||||
|
||||
sdkdelivery "git.novox.be/novox/mesh-sdk/go/delivery"
|
||||
|
||||
sdkdecl "git.novox.be/novox/mesh-sdk/go/declaration"
|
||||
)
|
||||
|
||||
@@ -56,3 +60,43 @@ func TestACompositionNamingAnObjectTheBucketLacksIsRefused(t *testing.T) {
|
||||
t.Fatalf("a composition naming a missing object was written: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Every file the provisioner fills stays filled in the compositions, a moved module's too: the node's own composition
|
||||
// carries the path, so the node-engine leaves its content to the provisioner (issue 1945, live on 2026-10-25 at 01:22:
|
||||
// ace's node-engine wrote claude-code's, node-env's and power's filled files empty, because the compositions dropped the
|
||||
// filled paths of every module moved into the node's own, and their resources say no content).
|
||||
func TestEveryFilledFileStaysFilledInTheCompositions(t *testing.T) {
|
||||
for _, node := range []string{"ace", "g14"} {
|
||||
body, fps := capturedBody(t, node)
|
||||
var d struct {
|
||||
Filled []string `json:"filled_files"`
|
||||
}
|
||||
if err := json.Unmarshal(body, &d); err != nil || len(d.Filled) == 0 {
|
||||
t.Fatalf("%s: the captured declaration fills nothing (%v)", node, err)
|
||||
}
|
||||
// power, claude-code and node-env have no fingerprint of the new form, so they move into the node's own.
|
||||
for _, m := range []string{"power", "claude-code", "node-env"} {
|
||||
delete(fps, m)
|
||||
}
|
||||
comps, _, err := compositionsOf(node, body, fps, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("%s: %v", node, err)
|
||||
}
|
||||
filled := map[string]bool{}
|
||||
for _, c := range comps {
|
||||
for _, p := range c.Filled {
|
||||
filled[p] = true
|
||||
}
|
||||
}
|
||||
for _, p := range d.Filled {
|
||||
if !filled[p] {
|
||||
t.Errorf("%s: %s is filled by the provisioner, and no composition says so", node, p)
|
||||
}
|
||||
}
|
||||
for key, c := range comps {
|
||||
if _, err := sdkdelivery.EncodeComposed(c); err != nil {
|
||||
t.Errorf("%s: %s: %v", node, key, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,11 +99,16 @@ func compositionsOf(node string, body []byte, fps map[string]string, manifests m
|
||||
}
|
||||
resources = append(resources, raw)
|
||||
}
|
||||
// A filled file of a module moved into the node's own composition is no module's file any more: the provisioner
|
||||
// fills it all the same, but a composition carries only its own module's filled paths.
|
||||
var filled []string
|
||||
// A filled file of a module moved into the node's own composition is no module's file any more, and the provisioner
|
||||
// fills it all the same: the node's own composition carries its path, so the node-engine leaves the content to the
|
||||
// provisioner and accepts its write. Dropping the path had the node-engine write those files empty, since their
|
||||
// resources say no content (issue 1945, live on 2026-10-25: claude-code's, node-env's and power's files on ace, g14
|
||||
// and shanks).
|
||||
var filled, ownFilled []string
|
||||
for _, p := range envelope.Filled {
|
||||
if !filledByMoved(envelope.Resources, p, inModule) {
|
||||
if filledByMoved(envelope.Resources, p, inModule) {
|
||||
ownFilled = append(ownFilled, p)
|
||||
} else {
|
||||
filled = append(filled, p)
|
||||
}
|
||||
}
|
||||
@@ -113,6 +118,15 @@ func compositionsOf(node string, body []byte, fps map[string]string, manifests m
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if len(ownFilled) > 0 {
|
||||
own, err := sdkdelivery.ComposedNodeKey(node)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
c := out[own]
|
||||
c.Filled = append(c.Filled, ownFilled...)
|
||||
out[own] = c
|
||||
}
|
||||
// A module the node runs that composes no resource of its own (all its needs met by others) still has its
|
||||
// composition, empty, at its fingerprint: its want names that composition (the assigner's seventh rule), and without
|
||||
// one no want could ever be written.
|
||||
|
||||
Reference in New Issue
Block a user