Name the checking program that judged a verdict (issue 1921)

The verdict gains judged-by: where the checking program was built, the
key its build is kept under and the heads it read, so the checker's
reads say who judged a check (ADR 0644, design 47's bootstrap delivery).

Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
This commit is contained in:
2026-11-06 22:07:41 +01:00
parent 0364fcccc0
commit 336fd73b8b
2 changed files with 55 additions and 1 deletions
+37
View File
@@ -179,6 +179,40 @@ type Verdict struct {
// carried over, by repository (ADR 0548 §5): the verdict was rewritten for Trunk and Beside by running only the packages
// whose digest the moves changed. Absent from a verdict judged whole, and from one still running.
CarriedFrom map[string]string `json:"carried-from,omitempty"`
// JudgedBy names the checking program that judged the check: where it was built, the key its build is kept under and
// the heads it read (novox/hq ADR 0644, ADR 0656; design 47's bootstrap delivery, *Its tool*). Absent in a value
// written before it.
JudgedBy *JudgedBy `json:"judged-by,omitempty"`
}
// JudgedBy is the checking program's build that judged a check: built at Program, kept under Key (RunKey), Built when
// this check's run built it rather than taking the kept one, over Heads.
type JudgedBy struct {
Program RunProgram `json:"program"`
Key string `json:"key"`
Built bool `json:"built,omitempty"`
Heads []RunHead `json:"heads"`
}
func (j *JudgedBy) check() error {
if j == nil {
return nil
}
if err := checkRepository(j.Program.Repository); err != nil || !askCommitOK.MatchString(j.Program.Commit) || j.Program.Package == "" {
return fmt.Errorf("delivery: the verdict is judged by a checking program built at no repository, full commit and package (%+v)", j.Program)
}
if !strings.HasPrefix(j.Key, "program-") {
return fmt.Errorf("delivery: the verdict's checking program is kept under %q, which is no program key", j.Key)
}
if len(j.Heads) == 0 {
return fmt.Errorf("delivery: the verdict's checking program read no head")
}
for _, h := range j.Heads {
if err := checkRepository(h.Repository); err != nil || !askCommitOK.MatchString(h.Commit) {
return fmt.Errorf("delivery: the verdict's checking program read %s at %q, which is no full commit", h.Repository, h.Commit)
}
}
return nil
}
func (c *Composition) check() error {
@@ -254,6 +288,9 @@ func (v Verdict) check() error {
if err := v.Composition.check(); err != nil {
return err
}
if err := v.JudgedBy.check(); err != nil {
return err
}
seen := map[string]bool{}
for _, level := range v.OverBound {
if err := checkLevel(level); err != nil {
+18 -1
View File
@@ -3,6 +3,7 @@ package delivery
import (
"encoding/json"
"errors"
"reflect"
"strconv"
"strings"
"testing"
@@ -314,6 +315,11 @@ func TestVerdictNewFieldsChecked(t *testing.T) {
"carried from an empty commit": {func(v *Verdict) { v.CarriedFrom = map[string]string{"novox/mesh-sdk": ""} }, []string{"carried-from", "mesh-sdk"}},
"carried over no move": {func(v *Verdict) { v.CarriedFrom = map[string]string{"novox/mesh-sdk": "aaaa"} }, []string{"nothing moved"}},
"a running verdict carried": {func(v *Verdict) { v.State, v.CarriedFrom = VerdictRunning, map[string]string{"novox/mesh-sdk": "9999"} }, []string{"running", "carried"}},
// 1921 (B0): the checking program that judged it.
"judged by no program": {func(v *Verdict) { v.JudgedBy = &JudgedBy{Key: "program-0123456789abcdef", Heads: judgedBy().Heads} }, []string{"checking program", "full commit"}},
"judged under no key": {func(v *Verdict) { j := judgedBy(); j.Key = "composer-1"; v.JudgedBy = &j }, []string{"composer-1"}},
"judged over no head": {func(v *Verdict) { j := judgedBy(); j.Heads = nil; v.JudgedBy = &j }, []string{"no head"}},
"judged over a branch": {func(v *Verdict) { j := judgedBy(); j.Heads[0].Commit = "main"; v.JudgedBy = &j }, []string{"novox/mesh-delivery", "main"}},
}
for name, c := range cases {
v := passVerdict()
@@ -338,7 +344,7 @@ func TestVerdictOldAndNewReadersAgree(t *testing.T) {
if err != nil {
t.Fatalf("the new reader of an old value: %v", err)
}
if v.Composition != nil || v.OverBound != nil || v.Beside != nil || v.CarriedFrom != nil || v.Levels[LevelUnit].Skipped != 0 || v.Levels[LevelUnit].Run != 12 {
if v.Composition != nil || v.OverBound != nil || v.Beside != nil || v.CarriedFrom != nil || v.JudgedBy != nil || v.Levels[LevelUnit].Skipped != 0 || v.Levels[LevelUnit].Run != 12 {
t.Errorf("an old value grew fields: %+v", v)
}
again, err := EncodeVerdict(v)
@@ -352,10 +358,16 @@ func TestVerdictOldAndNewReadersAgree(t *testing.T) {
n.Beside = map[string]string{"novox/mesh-catalog": "cccc"}
n.CarriedFrom = map[string]string{"novox/mesh-sdk": "9999"}
n.Composition.FPSet = "fps1:00"
j := judgedBy()
n.JudgedBy = &j
data, err := EncodeVerdict(n)
if err != nil {
t.Fatal(err)
}
// 1921 (B0): who judged it reads back whole.
if back, err := DecodeVerdict(data); err != nil || back.JudgedBy == nil || !reflect.DeepEqual(*back.JudgedBy, j) {
t.Errorf("judged by, read back: %+v %v", back.JudgedBy, err)
}
var ov oldVerdict
if err := json.Unmarshal(data, &ov); err != nil || ov.Group != "feat/x" || ov.State != VerdictPass || ov.Levels[LevelUnit].Run != 12 || ov.SDK == "" {
t.Errorf("the old reader of a new value: %+v, %v", ov, err)
@@ -658,3 +670,8 @@ func TestVerdictNamesEveryFailure(t *testing.T) {
t.Error("a verdict naming more than MaxFailures and the rest was written")
}
}
func judgedBy() JudgedBy {
return JudgedBy{Program: RunProgram{Repository: "novox/mesh-delivery", Commit: askCommit, Dir: "modules/mesh-delivery-checker", Package: "p"},
Key: "program-0123456789abcdef", Built: true, Heads: []RunHead{{Repository: "novox/mesh-delivery", Commit: askCommit}}}
}