Every check is judged by the checking program built from its heads (issue 1921)

The running checker asks the checking program twice on the build seat's job run: first the
heads' seat list, which the manifest validator's requests (change and trunk) and the
node-engine composer's carry; then the verdict of the facts it gathered. The program is built
at the group's mesh-delivery head, else at mesh-delivery's trunk, and its input is kept in the
checker's new state inputs as the exact bytes of its digest, read with checker_inputs. A run
ask no build node begins within 5 minutes is put once more, then fails the check naming the
job; a program that does not build or answer fails the check naming it, and the verdict
records who judged it (JudgedBy). A second step-seen hook on a context is added to the
first, so a try still sees its steps.

Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
This commit is contained in:
2026-11-06 22:58:15 +01:00
parent 043e3fb979
commit 63bbabacbf
24 changed files with 588 additions and 72 deletions
@@ -4,16 +4,18 @@
// verdict the judging rules give them, as one JSON line on its standard output (rules.Answer).
//
// mesh-checking-program -verdict
// mesh-checking-program -seats
//
// Asked -seats, it answers the seat list of the heads laid in the directory MESH_RUN_HEADS names (rules.SeatsAnswer).
// It refuses facts of a version it does not read, naming it, with exit 2.
package main
import (
"encoding/json"
"flag"
"fmt"
"io"
"io/fs"
"os"
"slices"
"git.novox.be/novox/mesh-sdk/go/delivery"
"mesh-delivery-checker/rules"
@@ -25,52 +27,25 @@ func main() {
// run is the command over its arguments, environment and outputs, answering its exit.
func run(args []string, getenv func(string) string, stdout, stderr io.Writer) int {
fs := flag.NewFlagSet("mesh-checking-program", flag.ContinueOnError)
fs.SetOutput(stderr)
verdict := fs.Bool("verdict", false, "answer the verdict of the facts in the input")
seats := fs.Bool("seats", false, "answer the seat list of the heads laid for it")
if err := fs.Parse(args); err != nil {
var heads fs.FS
if dir := getenv(delivery.RunHeadsEnv); dir != "" {
heads = os.DirFS(dir)
}
input := func() ([]byte, error) {
file := getenv(delivery.RunInputEnv)
if file == "" {
return nil, fmt.Errorf("%s names no file", delivery.RunInputEnv)
}
return os.ReadFile(file)
}
line, err := rules.Program(args, input, heads)
if err != nil {
if heads == nil && slices.Contains(args, "-seats") {
err = fmt.Errorf("no heads: %s names no directory", delivery.RunHeadsEnv)
}
fmt.Fprintf(stderr, "mesh-checking-program: %v\n", err)
return 2
}
refuse := func(format string, a ...any) int {
fmt.Fprintf(stderr, "mesh-checking-program: "+format+"\n", a...)
return 2
}
if *seats {
dir := getenv(delivery.RunHeadsEnv)
if dir == "" {
return refuse("no heads: %s names no directory", delivery.RunHeadsEnv)
}
answer, err := rules.SeatsOf(os.DirFS(dir))
if err != nil {
return refuse("%v", err)
}
line, err := json.Marshal(answer)
if err != nil {
return refuse("the seat list cannot be written: %v", err)
}
fmt.Fprintf(stdout, "%s\n", line)
return 0
}
if !*verdict {
return refuse("nothing asked: give -verdict or -seats")
}
file := getenv(delivery.RunInputEnv)
if file == "" {
return refuse("no input: %s names no file", delivery.RunInputEnv)
}
data, err := os.ReadFile(file)
if err != nil {
return refuse("the input cannot be read: %v", err)
}
facts, err := rules.DecodeFacts(data)
if err != nil {
return refuse("%v", err)
}
line, err := json.Marshal(rules.Judged(facts))
if err != nil {
return refuse("the verdict cannot be written: %v", err)
}
fmt.Fprintf(stdout, "%s\n", line)
return 0
}