// Package manifests reads every module's manifest as the catalogue's tree holds it and refuses what no judge could // read: a module.json that does not decode, and two manifests that name one module. // // It judges no manifest (novox/hq ADR 0578 ยง2): the checker judges every change's manifests with the indexer's judge, the // one judge, so the field, seat, bus and catalogue rules are said once, there. Until 2026-11 this check parsed each // manifest with mesh-sdk's strict parser and ran the rules between manifests (issue 774, power's bar item of // mesh-catalog ca8d6f33); that judgement moved to the checker, and what stays is the two refusals that are about the // tree, not a manifest's rules. package manifests import ( "fmt" "os" "path/filepath" "sort" "git.novox.be/novox/mesh-sdk/go/catalogue" ) // Problems is what is wrong with the tree's manifests under root/modules, one line each: a module.json whose bytes are // no manifest (catalogue.Decode: not JSON, or a field of the wrong shape), then a module named by two manifests. func Problems(root string) ([]string, error) { files, err := filepath.Glob(filepath.Join(root, "modules", "*", "module.json")) if err != nil { return nil, err } sort.Strings(files) var out []string named := map[string]bool{} for _, f := range files { raw, err := os.ReadFile(f) if err != nil { return nil, err } rel, _ := filepath.Rel(root, f) m, err := catalogue.Decode(raw) if err != nil { out = append(out, fmt.Sprintf("%s: %v", rel, err)) continue } if named[m.Module] { out = append(out, fmt.Sprintf("%s: %s was already given; two manifests name one module", rel, m.Module)) continue } named[m.Module] = true } return out, nil }