B0's shape wins: the running checker asks and records facts, the checking program decides. The registry's types win: the rules and the program read the generated checker contract and the domain SDK, and no mesh-sdk delivery import is left. The registry's series, renames and unparsed seat definitions become facts with their refusals as rules; the tagged versions ride on the case. The program reads the heads' seat definitions through sdk/seatdefs and the running checker lays them over its reader's list by seat, reading no file of the heads: the reader's list is larger than a run input's bound. Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
100 lines
4.7 KiB
Go
100 lines
4.7 KiB
Go
package rules
|
|
|
|
import (
|
|
"fmt"
|
|
"maps"
|
|
"slices"
|
|
"strings"
|
|
|
|
"git.novox.be/novox/mesh-contracts/go/seats/meshconfig"
|
|
)
|
|
|
|
// The refusals of what the running checker asked of other seats for a check (milestone 47/G): it asks and records the
|
|
// answers as facts, and these rules decide what fails.
|
|
|
|
// RenamesSeat is the verb a change that brings or drops a `renamed-from` is asked of (design 32).
|
|
var RenamesSeat = "seat:" + meshconfig.Seat + "." + meshconfig.VerbRenames
|
|
|
|
// Renames is what one module of a member brings and drops of `renamed-from` (key to the old key), and how the seat
|
|
// mesh-config's verb renames answered for it: Answer when it answered; else Unasked says why it was not asked or did not
|
|
// answer, NotServed that its holder does not serve the verb. Unread says the module's manifests could not be read.
|
|
type Renames struct {
|
|
Module string `json:"module"`
|
|
Key string `json:"key"`
|
|
Brought map[string]string `json:"brought,omitempty"`
|
|
Dropped map[string]string `json:"dropped,omitempty"`
|
|
Answer *meshconfig.RenamesAnswer `json:"answer,omitempty"`
|
|
Unasked string `json:"unasked,omitempty"`
|
|
NotServed bool `json:"not-served,omitempty"`
|
|
Unread string `json:"unread,omitempty"`
|
|
}
|
|
|
|
// JudgeRenames fails a rename the seat cannot move the value of, and the drop of a `renamed-from` while its window is
|
|
// open on a node; it says which module the seat answered for.
|
|
func JudgeRenames(r Renames) (failed []FailedFirst, notes []string) {
|
|
at := func(words string) { failed = append(failed, FailedFirst{Machine: meshconfig.Seat, Words: words}) }
|
|
switch {
|
|
case r.Unread != "":
|
|
at(fmt.Sprintf("%s (%s): its config renames cannot be judged: %s", r.Module, r.Key, r.Unread))
|
|
return failed, nil
|
|
case r.NotServed:
|
|
for _, key := range slices.Sorted(maps.Keys(r.Brought)) {
|
|
at(fmt.Sprintf("%s (%s) renames %s from %s: refused, %s, so the value cannot be moved", r.Module, r.Key, key, r.Brought[key], r.Unasked))
|
|
}
|
|
for _, key := range slices.Sorted(maps.Keys(r.Dropped)) {
|
|
at(fmt.Sprintf("%s (%s) drops renamed-from %s of %s: refused, %s, so whether its window is open is not known", r.Module, r.Key, r.Dropped[key], key, r.Unasked))
|
|
}
|
|
return failed, nil
|
|
case r.Answer == nil && r.Unasked == "":
|
|
at(fmt.Sprintf("%s (%s) changes a renamed-from, and this checker cannot ask %s", r.Module, r.Key, RenamesSeat))
|
|
return failed, nil
|
|
case r.Answer == nil:
|
|
at(fmt.Sprintf("%s (%s) changes a renamed-from, and the check cannot ask %s: %s", r.Module, r.Key, RenamesSeat, r.Unasked))
|
|
return failed, nil
|
|
}
|
|
for _, key := range slices.Sorted(maps.Keys(r.Dropped)) {
|
|
for _, n := range r.Answer.Renames {
|
|
if n.Module == r.Module && n.From == r.Dropped[key] && n.To == key && len(n.Open) > 0 {
|
|
open := slices.Sorted(slices.Values(n.Open))
|
|
at(fmt.Sprintf("%s (%s) drops renamed-from %s of %s while its rename window is open on %s", r.Module, r.Key, n.From, key, strings.Join(open, ", ")))
|
|
}
|
|
}
|
|
}
|
|
return failed, []string{fmt.Sprintf("%s.%s answered for %s (%s)", meshconfig.Seat, meshconfig.VerbRenames, r.Module, r.Key)}
|
|
}
|
|
|
|
// SeatDefinitionsMachine names what refused a seat definition in a verdict's failure.
|
|
const SeatDefinitionsMachine = "seat-definitions"
|
|
|
|
// UnparsedSeat is one seat definition of a pull request's head that does not parse, as the indexer keeps it in its state
|
|
// seat-definitions: the seat (the contracts module's name when its index did not parse), its module's directory and the
|
|
// indexer's words of why.
|
|
type UnparsedSeat struct {
|
|
Seat string `json:"seat"`
|
|
Module string `json:"module"`
|
|
Directory string `json:"directory"`
|
|
Why string `json:"why"`
|
|
}
|
|
|
|
// Unparsed is what the indexer keeps of one pull request's seat definitions that do not parse; Unread says why its state
|
|
// could not be read.
|
|
type Unparsed struct {
|
|
Key string `json:"key"`
|
|
Seats []UnparsedSeat `json:"seats,omitempty"`
|
|
Unread string `json:"unread,omitempty"`
|
|
}
|
|
|
|
// JudgeUnparsed fails a pull request whose head's seat definition does not parse, naming the seat and where it lives
|
|
// (design 26; the lead's ruling on A2i's finding 1), and one whose seat definitions cannot be read, since none is then
|
|
// known to parse.
|
|
func JudgeUnparsed(u Unparsed) []FailedFirst {
|
|
if u.Unread != "" {
|
|
return []FailedFirst{{Machine: SeatDefinitionsMachine, Words: fmt.Sprintf("%s: the indexer's seat definitions of it cannot be read, so none is known to parse: %s", u.Key, u.Unread)}}
|
|
}
|
|
var out []FailedFirst
|
|
for _, s := range u.Seats {
|
|
out = append(out, FailedFirst{Machine: SeatDefinitionsMachine, Words: fmt.Sprintf("%s: the seat definition of %s (module %s, %s) does not parse: %s", u.Key, s.Seat, s.Module, s.Directory, s.Why)})
|
|
}
|
|
return out
|
|
}
|