package main import ( "encoding/json" "os" "testing" ) // **The archive places exactly one file, /usr/local/bin/mesh-cli**, and the console's address is one file more (review of novox/hq ADR 0272): one archive // resource, unpacking one artifact into /usr/local/bin, and that artifact a compiled Go bundle — the builder writes // such a bundle as its binary alone (`go build -o /`), named mesh-cli — with nothing the runtime would // load or put beside it. A second file in the bundle, or a second resource writing there, fails here. func TestTheArchivePlacesExactlyOneFileAndTheConsolesAddressOne(t *testing.T) { raw, err := os.ReadFile("../../module.json") if err != nil { t.Fatal(err) } var m struct { Resources []map[string]any `json:"resources"` Build struct { Artifacts []map[string]any `json:"artifacts"` } `json:"build"` } if err := json.Unmarshal(raw, &m); err != nil { t.Fatal(err) } // Beside the program, one directory and one file: the console's address, from the mcp-endpoint it requires // (novox/hq issue 1126). Nothing else. var r map[string]any for _, res := range m.Resources { switch { case res["type"] == "archive": if r != nil { t.Fatalf("two archives: %v", res) } r = res case res["type"] == "directory" && res["path"] == "/etc/mesh-cli": case res["type"] == "file" && res["path"] == consoleFile && res["template"] == "files/console": default: t.Fatalf("the module declares %v beside the program and the console's address", res) } } if len(m.Resources) != 3 || r == nil || r["path"] != "/usr/local/bin" { t.Fatalf("its resources are %v", m.Resources) } // The build has a second artifact, the files archive the controller reads the templates back from; it // places no file. The artifact the resource unpacks is the one that does. var a map[string]any for _, candidate := range m.Build.Artifacts { if candidate["name"] == r["artifact"] { if a != nil { t.Fatalf("two artifacts are named %v", r["artifact"]) } a = candidate } else if candidate["kind"] != "archive" || candidate["from"] != "files" { t.Fatalf("it builds %v beside the artifact that places the file", candidate) } } if a == nil { t.Fatalf("no artifact is named %v", r["artifact"]) } if a["name"] != r["artifact"] || a["kind"] != "bundle" || a["language"] != "go" || a["binary"] != "mesh-cli" || a["from"] != "cmd/mesh-cli" { t.Fatalf("its artifact is %v, unpacked as %v", a, r["artifact"]) } for _, extra := range []string{"loads", "env", "context", "files"} { if _, has := a[extra]; has { t.Fatalf("its artifact says %q, which would put more than the binary in the bundle or load it", extra) } } entries, err := os.ReadDir(".") if err != nil { t.Fatal(err) } for _, e := range entries { if e.IsDir() { t.Fatalf("cmd/mesh-cli holds a directory %s, which a build could carry into the bundle", e.Name()) } } } // The console's address is written from the mcp-endpoint the module requires, as claude-code writes it, so it follows // the port node-tools is bound on. func TestTheConsolesAddressIsBoundFromTheEndpoint(t *testing.T) { raw, err := os.ReadFile("../../module.json") if err != nil { t.Fatal(err) } var m struct { Requires []string `json:"requires"` } if err := json.Unmarshal(raw, &m); err != nil || len(m.Requires) != 1 || m.Requires[0] != "mcp-endpoint" { t.Fatalf("it requires %v (%v)", m.Requires, err) } tpl, err := os.ReadFile("../../files/console") if err != nil || string(tpl) != "http://127.0.0.1:${bound:mcp-endpoint:port}/mcp\n" { t.Fatalf("files/console is %q (%v)", tpl, err) } }