ADR 0565 §11's catalog check: every recorder records through mesh-hand-acts. The fallbacks are listed with why, and the list only shrinks.
110 lines
3.1 KiB
Go
110 lines
3.1 KiB
Go
// Command handacts refuses a manifest that records into the controller's hand-act log (novox/hq ADR 0565 §11): every
|
|
// recorder records through the seat mesh-hand-acts from its delivery, so no manifest invokes
|
|
// `seat:mesh-controller.hand-act`, `.warranted` or `.drill`. The recorders' fallbacks to the controller's log while the
|
|
// seat has no holder are named in checks/handacts/fallbacks, each module and verb with why; that list only shrinks, and
|
|
// an entry whose module no longer invokes the verb is refused too.
|
|
//
|
|
// go run . <catalog root>
|
|
//
|
|
// Exits 1 on a finding.
|
|
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"sort"
|
|
"strings"
|
|
)
|
|
|
|
// Verbs are the controller's hand-act verbs, as a manifest invokes them, and Allowed the list of named fallbacks.
|
|
var Verbs = []string{"hand-act", "warranted", "drill"}
|
|
|
|
const (
|
|
invokePrefix = "seat:mesh-controller."
|
|
Allowed = "checks/handacts/fallbacks"
|
|
)
|
|
|
|
// Findings is every refusal in the catalog at root, sorted.
|
|
func Findings(root string) ([]string, error) {
|
|
allowed := map[string]bool{}
|
|
raw, err := os.ReadFile(filepath.Join(root, Allowed))
|
|
if err != nil && !os.IsNotExist(err) {
|
|
return nil, err
|
|
}
|
|
for _, line := range strings.Split(string(raw), "\n") {
|
|
if f := strings.Fields(line); len(f) >= 3 && !strings.HasPrefix(f[0], "#") {
|
|
allowed[f[0]+" "+f[1]] = true
|
|
} else if len(f) > 0 && !strings.HasPrefix(f[0], "#") {
|
|
return nil, fmt.Errorf("%s: %q is not `<module> <verb> <why>`", Allowed, line)
|
|
}
|
|
}
|
|
manifests, err := filepath.Glob(filepath.Join(root, "modules", "*", "module.json"))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var out []string
|
|
invoked := map[string]bool{}
|
|
for _, path := range manifests {
|
|
raw, err := os.ReadFile(path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var m struct {
|
|
Module string `json:"module"`
|
|
Invokes []string `json:"invokes"`
|
|
}
|
|
if json.Unmarshal(raw, &m) != nil || m.Module == "mesh-controller" {
|
|
continue
|
|
}
|
|
for _, inv := range m.Invokes {
|
|
verb, ok := strings.CutPrefix(strings.TrimSpace(inv), invokePrefix)
|
|
if !ok || !contains(Verbs, verb) {
|
|
continue
|
|
}
|
|
invoked[m.Module+" "+verb] = true
|
|
if !allowed[m.Module+" "+verb] {
|
|
out = append(out, fmt.Sprintf("%s invokes %s%s: record through seat:mesh-hand-acts.%s (novox/hq ADR 0565 §11), "+
|
|
"or name the fallback in %s", m.Module, invokePrefix, verb, verb, Allowed))
|
|
}
|
|
}
|
|
}
|
|
for entry := range allowed {
|
|
if !invoked[entry] {
|
|
out = append(out, fmt.Sprintf("%s names %q, which is no longer invoked: take it off the list, which only shrinks",
|
|
Allowed, entry))
|
|
}
|
|
}
|
|
sort.Strings(out)
|
|
return out, nil
|
|
}
|
|
|
|
func contains(list []string, s string) bool {
|
|
for _, x := range list {
|
|
if x == s {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func main() {
|
|
if len(os.Args) != 2 {
|
|
fmt.Fprintln(os.Stderr, "usage: handacts <catalog root>")
|
|
os.Exit(2)
|
|
}
|
|
found, err := Findings(os.Args[1])
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
os.Exit(1)
|
|
}
|
|
for _, f := range found {
|
|
fmt.Println(f)
|
|
}
|
|
if len(found) > 0 {
|
|
os.Exit(1)
|
|
}
|
|
fmt.Println("no manifest records into the controller's hand-act log but the fallbacks named")
|
|
}
|