Assigner: the gate's answer, source and merge are the delivery client's and the seat's, the verdict words the checker client's (ADR 0634 §2, §4; issue 1966)

Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
This commit is contained in:
2026-11-05 16:04:06 +01:00
parent 70865842f2
commit 05b7dbce48
8 changed files with 54 additions and 56 deletions
@@ -10,6 +10,7 @@ import (
"git.novox.be/novox/mesh-contracts/go/clients/nodeengineclient"
mwc "git.novox.be/novox/mesh-contracts/placement/go/clients/meshwantsclient"
"git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient"
mdcc "git.novox.be/novox/mesh-delivery/contracts/go/clients/meshdeliverycheckerclient"
"git.novox.be/novox/mesh-delivery/contracts/go/clients/meshdeliveryclient"
"git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog"
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-assigner/asks"
@@ -898,7 +899,7 @@ func (b *bed) answer(t *testing.T, key, option string) {
// answerTo is answer to the ask with this id (the router's warrant names it).
func (b *bed) answerTo(t *testing.T, key, option, askID string) {
t.Helper()
v, err := delivery.EncodeAnswer(delivery.Answer{Option: option, Warrant: askID + "@2026-10-24T12:00:00Z", Words: "the operator"})
v, err := meshdeliveryclient.EncodeAnswer(meshdeliveryclient.Answer{Option: option, Warrant: askID + "@2026-10-24T12:00:00Z", Words: "the operator"})
if err != nil {
t.Fatal(err)
}
@@ -1310,7 +1311,7 @@ func TestAProposalIsAnsweredApprovedAndWritten(t *testing.T) {
}
silent := q.(proposed).Proposal
decided := proposalNow(silent.ID, "decided without its silent nodes", func(p mma.Proposal) bool { return p.State == mmac.ProposalAsked })
if decided.Verdict == nil || decided.Verdict.State != delivery.VerdictPass ||
if decided.Verdict == nil || decided.Verdict.State != mdcc.VerdictPass ||
!strings.Contains(strings.Join(decided.Verdict.Notes, "; "), "no answer from") || !strings.Contains(strings.Join(decided.Verdict.Notes, "; "), "laptop (offline)") {
t.Errorf("the silent node's verdict = %+v", decided.Verdict)
}
@@ -10,7 +10,9 @@ import (
watchdogs "git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshwatchdogs"
mwc "git.novox.be/novox/mesh-contracts/placement/go/clients/meshwantsclient"
"git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient"
mdc "git.novox.be/novox/mesh-delivery/contracts/go/clients/meshdeliveryclient"
"git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog"
mdseat "git.novox.be/novox/mesh-delivery/contracts/go/seats/meshdelivery"
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-assigner/asks"
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-builder/builds"
"git.novox.be/novox/mesh-delivery/modules/mesh-grants/grantsstate"
@@ -150,7 +152,7 @@ func TestAnAnswerCountsOnlyForTheAskingItAnswered(t *testing.T) {
return mustAskID(a)
}
first := put(100)
v, _ := delivery.EncodeAnswer(delivery.Answer{Option: "release", Warrant: first + "@2026-10-25T01:00:00Z", Words: "the operator"})
v, _ := mdc.EncodeAnswer(mdc.Answer{Option: "release", Warrant: first + "@2026-10-25T01:00:00Z", Words: "the operator"})
p.w.put(buckets.Answers, key, v)
if !p.answeredWith(key, "release") {
t.Fatal("the answer to the ask that stands is not taken")
@@ -419,7 +421,7 @@ func putOfTheBus(t *testing.T) {
t.Fatal("the bus's want was written before the operator's warrant")
}
world(buckets.Asks, akey, asksKV.values[akey])
yes, _ := delivery.EncodeAnswer(delivery.Answer{Option: assign.OptionYes, Warrant: a.Ask.ID + "@2026-10-25T22:01:00Z", Words: "the operator, verified"})
yes, _ := mdc.EncodeAnswer(mdc.Answer{Option: assign.OptionYes, Warrant: a.Ask.ID + "@2026-10-25T22:01:00Z", Words: "the operator, verified"})
world(buckets.Answers, akey, yes)
if got := step(); got.Step != puts.Snapshot {
t.Fatalf("on the warrant the put stands at %s: %s", got.Step, got.Words)
@@ -465,7 +467,7 @@ func putOfTheBus(t *testing.T) {
t.Fatalf("put again, it stands at %s (%s); its ask %q, %v; the first ask was %q", again.Step, again.Words, a2.Ask.ID, err, a.Ask.ID)
}
world(buckets.Asks, akey, asksKV.values[akey])
yes2, _ := delivery.EncodeAnswer(delivery.Answer{Option: assign.OptionYes, Warrant: a2.Ask.ID + "@2026-10-25T22:03:00Z", Words: "the operator, verified"})
yes2, _ := mdc.EncodeAnswer(mdc.Answer{Option: assign.OptionYes, Warrant: a2.Ask.ID + "@2026-10-25T22:03:00Z", Words: "the operator, verified"})
world(buckets.Answers, akey, yes2)
if got := step(); got.Step != puts.Snapshot {
t.Fatalf("on the second warrant the put stands at %s: %s", got.Step, got.Words)
@@ -934,19 +936,19 @@ func aReleasesApproveAnswersTheMoveOfItsBuildAlone(t *testing.T) {
p.logf = t.Logf
mod, _ := meshcatalogclient.EncodeModule(meshcatalog.ModulesByModuleValue{Fp2: fpTest, Repository: "novox/web", Commit: commit, Src: 7, FpSrc: c.fpSrc, Path: meshcatalogclient.RootPath})
p.w.put(buckets.Modules, "web", mod)
src, _ := delivery.EncodeSource(delivery.Source{Group: "feat/web", Heads: map[string]string{"novox/web": commit}})
p.w.putEntry(buckets.Source, delivery.SourceMainKey, src, 7, time.Now())
later, _ := delivery.EncodeSource(delivery.Source{Group: "feat/other", Heads: map[string]string{"novox/web": commit, "novox/x": commit}})
p.w.putEntry(buckets.Source, delivery.SourceMainKey, later, 8, time.Now()) // a later merge leaves revision 7's release
src, _ := mdc.EncodeSource(mdseat.SourceByMainValue{Group: "feat/web", Heads: map[string]string{"novox/web": commit}})
p.w.putEntry(buckets.Source, mdc.SourceMainKey, src, 7, time.Now())
later, _ := mdc.EncodeSource(mdseat.SourceByMainValue{Group: "feat/other", Heads: map[string]string{"novox/web": commit, "novox/x": commit}})
p.w.putEntry(buckets.Source, mdc.SourceMainKey, later, 8, time.Now()) // a later merge leaves revision 7's release
if c.mergedAt != "" {
merge, err := delivery.EncodeMerge(delivery.Merge{Group: "feat/web", Ask: "merge.feat_web.0123456789ab", Pulls: []delivery.MergePull{
{Head: delivery.Head{Repository: "novox/web", Number: 3, Head: strings.Repeat("3", 40)}, State: delivery.MergeMerged, Commit: c.mergedAt}}})
merge, err := mdc.EncodeMerge(mdseat.MergesByGroupValue{Group: "feat/web", Ask: "merge.feat_web.0123456789ab", Pulls: []mdseat.MergesByGroupValuePullsItem{
{Repository: "novox/web", Number: 3, Head: strings.Repeat("3", 40), State: string(mdc.MergeMerged), Commit: c.mergedAt}}})
if err != nil {
t.Fatal(err)
}
p.w.put(buckets.Merges, "feat/web", merge)
other, err := delivery.EncodeMerge(delivery.Merge{Group: "feat/other", Ask: "merge.feat_other.0123456789ab", Pulls: []delivery.MergePull{
{Head: delivery.Head{Repository: "novox/x", Number: 4, Head: strings.Repeat("4", 40)}, State: delivery.MergeMerged, Commit: commit}}})
other, err := mdc.EncodeMerge(mdseat.MergesByGroupValue{Group: "feat/other", Ask: "merge.feat_other.0123456789ab", Pulls: []mdseat.MergesByGroupValuePullsItem{
{Repository: "novox/x", Number: 4, Head: strings.Repeat("4", 40), State: string(mdc.MergeMerged), Commit: commit}}})
if err != nil {
t.Fatal(err)
}
@@ -1058,7 +1060,7 @@ func aPlacedNodesWantsNameTheBuildAloneAndItsYesComesFromItsHave(t *testing.T) {
t.Fatal(err)
}
put(buckets.Asks, akey, asksKV.values[akey])
yes, _ := delivery.EncodeAnswer(delivery.Answer{Option: assign.OptionYes, Warrant: a.Ask.ID + "@2026-10-26T19:00:00Z", Words: "the operator"})
yes, _ := mdc.EncodeAnswer(mdc.Answer{Option: assign.OptionYes, Warrant: a.Ask.ID + "@2026-10-26T19:00:00Z", Words: "the operator"})
put(buckets.Answers, akey, yes)
p.wants(context.Background())
sync()
@@ -1085,7 +1087,7 @@ func TestAnApprovedPlacementCallsNoControllerVerb(t *testing.T) {
p.publish = func(event string, _ any, _ string) error { said = append(said, event); return nil }
prop := mma.Proposal{ID: "p-one", By: "operator@laptop", Why: "move web"}
change := plc.ChangeOf(mma.Placement{Node: "anchor"}, mma.Placement{Node: "anchor", Modules: []mma.PlacedModule{{Module: "web"}}})
p.followWrite(prop, delivery.Answer{}, []plc.Change{change})
p.followWrite(prop, mdc.Answer{}, []plc.Change{change})
if len(bus.calls) != 0 || !slices.Equal(said, []string{mma.EventPlacementChanged}) {
t.Fatalf("calls = %d, said = %v", len(bus.calls), said)
}
@@ -8,6 +8,8 @@ import (
"git.novox.be/novox/mesh-contracts/go/clients/nodeengineclient"
"git.novox.be/novox/mesh-contracts/go/seats/nodeengine"
"git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient"
mdcc "git.novox.be/novox/mesh-delivery/contracts/go/clients/meshdeliverycheckerclient"
mdc "git.novox.be/novox/mesh-delivery/contracts/go/clients/meshdeliveryclient"
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-assigner/asks"
"maps"
"mesh-delivery-assigner/internal/buckets"
@@ -328,11 +330,11 @@ func (p *passer) stepProposal(ctx context.Context, prop mma.Proposal, rev uint64
}
prop.Verdict = &v
switch v.State {
case delivery.VerdictFail:
case mdcc.VerdictFail:
prop.State, prop.Ask = mmac.ProposalFailed, ""
case plc.VerdictWaits:
prop.State, prop.Ask = mmac.ProposalAnswering, ""
case delivery.VerdictPass:
case mdcc.VerdictPass:
if prop.State != mmac.ProposalAsked || again {
var ok bool
if prop, ok = p.ask(ctx, prop, akey, judge.Brief(prop, v)); !ok {
@@ -558,7 +560,7 @@ func (p *passer) addNode(ctx context.Context, prop mma.Proposal, revs map[string
_ = p.kvs[plc.ProposalsBucket].Delete(ctx, prop.ID)
p.w.put(plc.ProposalsBucket, prop.ID, nil)
w := prop.Warrant
p.sayChanged(prop, delivery.Answer{Option: assign.OptionYes, Warrant: w.Warrant,
p.sayChanged(prop, mdc.Answer{Option: assign.OptionYes, Warrant: w.Warrant,
Words: fmt.Sprintf("the operator approved the machine %s at %s through the enrolment's ask %s", w.Node, w.Address, w.Ask)},
[]plc.Change{c})
}
@@ -585,14 +587,14 @@ func (p *passer) removeNode(ctx context.Context, prop mma.Proposal, current map[
_ = p.kvs[plc.ProposalsBucket].Delete(ctx, prop.ID)
p.w.put(plc.ProposalsBucket, prop.ID, nil)
w := prop.Warrant
p.sayChanged(prop, delivery.Answer{Option: assign.OptionYes, Warrant: w.Warrant,
p.sayChanged(prop, mdc.Answer{Option: assign.OptionYes, Warrant: w.Warrant,
Words: fmt.Sprintf("the machine %s left placement: its enrolment (ask %s) ended before it confirmed", w.Node, w.Ask)},
[]plc.Change{c})
}
// followWrite follows the keys a warrant wrote: the warrant recorded and placement-changed said. No verb of the
// controller is called: the placement is the one source of where modules run (ADR 0567 §8, issue 774).
func (p *passer) followWrite(prop mma.Proposal, answer delivery.Answer, changes []plc.Change) {
func (p *passer) followWrite(prop mma.Proposal, answer mdc.Answer, changes []plc.Change) {
if len(changes) == 0 {
return
}
@@ -610,7 +612,7 @@ func sortedNodes(m map[string]*mma.Placement) []string {
}
// sayChanged says placement-changed for the keys written.
func (p *passer) sayChanged(prop mma.Proposal, answer delivery.Answer, changes []plc.Change) {
func (p *passer) sayChanged(prop mma.Proposal, answer mdc.Answer, changes []plc.Change) {
if len(changes) == 0 {
return
}
@@ -8,8 +8,10 @@ import (
watchdogs "git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshwatchdogs"
mwc "git.novox.be/novox/mesh-contracts/placement/go/clients/meshwantsclient"
"git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient"
mdc "git.novox.be/novox/mesh-delivery/contracts/go/clients/meshdeliveryclient"
"git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog"
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-builder/builds"
"git.novox.be/novox/mesh-delivery/sdk/trunk"
"git.novox.be/novox/mesh-sdk/go/keys"
"maps"
"mesh-delivery-assigner/internal/buckets"
@@ -88,8 +90,8 @@ func (w *world) putEntry(bucket, key string, value []byte, revision uint64, at t
if bucket == plc.PlacementBucket {
_, _ = w.placement.Put(key, value, revision, false) // put took it already; this is its revision
}
if bucket == buckets.Source && key == delivery.SourceMainKey {
if s, err := delivery.DecodeSource(value); err == nil && s.Group != "" {
if bucket == buckets.Source && key == mdc.SourceMainKey {
if s, err := mdc.DecodeSource(value); err == nil && s.Group != "" {
w.sourceGroups[revision] = s.Group
}
}
@@ -108,7 +110,7 @@ func (w *world) release(module, fp string) (string, bool) {
w.mu.Lock()
group := w.sourceGroups[uint64(t.FpSrc)]
w.mu.Unlock()
key, err := delivery.MergesKey(group)
key, err := mdc.MergesKey(group)
if group == "" || err != nil {
return "", false
}
@@ -116,12 +118,12 @@ func (w *world) release(module, fp string) (string, bool) {
if raw == nil {
return "", false
}
merge, err := delivery.DecodeMerge(raw)
merge, err := mdc.DecodeMerge(raw)
if err != nil {
return "", false
}
for _, pull := range merge.Pulls {
if pull.State == delivery.MergeMerged && pull.Commit == t.Commit && delivery.SameRepository(pull.Repository, t.Repository) {
if pull.State == string(mdc.MergeMerged) && pull.Commit == t.Commit && trunk.SameRepository(pull.Repository, t.Repository) {
return group, true
}
}
@@ -503,14 +505,14 @@ func (w *world) composed(node, module, fp string) (assign.ComposedDigest, bool)
}
// answer is the teller's answer to the ask at key (mesh-delivery-teller_answers, the same key), and whether there is one.
func (w *world) answer(key string) (delivery.Answer, bool) {
func (w *world) answer(key string) (mdc.Answer, bool) {
w.mu.Lock()
value, ok := w.values[buckets.Answers][key]
w.mu.Unlock()
if !ok {
return delivery.Answer{}, false
return mdc.Answer{}, false
}
a, err := delivery.DecodeAnswer(value)
a, err := mdc.DecodeAnswer(value)
return a, err == nil
}
@@ -6,12 +6,9 @@ import (
"git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog"
"git.novox.be/novox/mesh-delivery/modules/mesh-grants/grantsstate"
"mesh-delivery-assigner/internal/buckets"
"slices"
"strings"
"testing"
"time"
"git.novox.be/novox/mesh-sdk/go/delivery"
)
// fakeManifests is the indexer's manifests bucket in memory.
@@ -37,15 +34,6 @@ func (f fakeManifests) get(_ context.Context, key string) ([]byte, error) {
func fp(c byte) string { return meshcatalogclient.SourcePrefix2 + strings.Repeat(string(c), 64) }
func pull(repo string, number int, modules map[string]delivery.CandidateModule) delivery.CandidatePull {
p := delivery.CandidatePull{Head: delivery.Head{Repository: repo, Number: number, Head: strings.Repeat("3", 40)}, Fps: modules}
for m := range modules {
p.Modules = append(p.Modules, m)
}
slices.Sort(p.Modules)
return p
}
// Review round 1 (items 3 and 4): the world counts the values a key takes, so a have written again after an answer is seen.
func theWorldCountsTheValuesAKeyTakes(t *testing.T) {
w := newWorld()
+3
View File
@@ -64,3 +64,6 @@ require git.novox.be/novox/mesh-delivery/modules/mesh-delivery-view/viewstate v0
replace git.novox.be/novox/mesh-delivery/modules/mesh-delivery-view/viewstate => ../mesh-delivery-view/viewstate
require git.novox.be/novox/mesh-contracts/placement/go/clients/meshwantsclient v0.0.0-00010101000000-000000000000
require git.novox.be/novox/mesh-delivery/contracts/go/clients/meshdeliverycheckerclient v0.0.0-00010101000000-000000000000
replace git.novox.be/novox/mesh-delivery/contracts/go/clients/meshdeliverycheckerclient => ../../contracts/go/clients/meshdeliverycheckerclient
@@ -9,6 +9,7 @@ import (
"encoding/json"
"fmt"
"git.novox.be/novox/mesh-contracts/go/seats/nodeengine"
mdcc "git.novox.be/novox/mesh-delivery/contracts/go/clients/meshdeliverycheckerclient"
"reflect"
"sort"
"strconv"
@@ -17,7 +18,6 @@ import (
nec "git.novox.be/novox/mesh-contracts/go/clients/nodeengineclient"
mma "git.novox.be/novox/mesh-contracts/placement/go/seats/meshmoduleassigner"
"git.novox.be/novox/mesh-sdk/go/delivery"
plc "mesh-delivery-assigner/internal/placement"
)
@@ -169,11 +169,11 @@ func JudgeAnswers(p mma.Proposal, intended map[string]map[string]bool, answers m
}
switch {
case len(v.Fails) > 0:
v.State = delivery.VerdictFail
v.State = mdcc.VerdictFail
case len(waiting) > 0:
v.State = plc.VerdictWaits
default:
v.State = delivery.VerdictPass
v.State = mdcc.VerdictPass
}
return v
}
@@ -259,7 +259,7 @@ func differenceWords(d nodeengine.CandidateDiffers) string {
// shownValue bounds a value named in a brief.
const shownValue = 60
// walk follows a differing path (delivery.DifferingPaths: keys joined by dots, a key may hold dots, and a JSON value
// walk follows a differing path (the node-engine's DifferingPaths: keys joined by dots, a key may hold dots, and a JSON value
// written in a string is read as JSON) through a body, answering the keys it passed and the value at its end.
func walk(body, path string) (keys []string, value any, ok bool) {
var v any
@@ -2,13 +2,13 @@ package judge
import (
"git.novox.be/novox/mesh-contracts/go/seats/nodeengine"
mdcc "git.novox.be/novox/mesh-delivery/contracts/go/clients/meshdeliverycheckerclient"
"slices"
"strings"
"testing"
"time"
mma "git.novox.be/novox/mesh-contracts/placement/go/seats/meshmoduleassigner"
"git.novox.be/novox/mesh-sdk/go/delivery"
plc "mesh-delivery-assigner/internal/placement"
)
@@ -49,22 +49,22 @@ func TestJudge(t *testing.T) {
words string
marked string
}{
{"all the same", false, map[string]*nodeengine.CandidateAnswer{"anchor": same(7), "laptop": same(8)}, nil, delivery.VerdictPass, "", ""},
{"all the same", false, map[string]*nodeengine.CandidateAnswer{"anchor": same(7), "laptop": same(8)}, nil, mdcc.VerdictPass, "", ""},
{"a module added where intended", false, map[string]*nodeengine.CandidateAnswer{"anchor": {Proposal: "p-one", Revision: 7, Verdict: nodeengine.CandidateAnswerVerdictDiffers,
Added: []nodeengine.CandidateAdded{{Module: "web", Unissued: []string{"its own secret"}}}}, "laptop": same(8)}, nil, delivery.VerdictPass, "", ""},
{"a difference not computed passes, marked", false, map[string]*nodeengine.CandidateAnswer{"anchor": differs(7, "mail"), "laptop": same(8)}, nil, delivery.VerdictPass, "", "mail"},
Added: []nodeengine.CandidateAdded{{Module: "web", Unissued: []string{"its own secret"}}}}, "laptop": same(8)}, nil, mdcc.VerdictPass, "", ""},
{"a difference not computed passes, marked", false, map[string]*nodeengine.CandidateAnswer{"anchor": differs(7, "mail"), "laptop": same(8)}, nil, mdcc.VerdictPass, "", "mail"},
{"the seed carries a difference, named", true, map[string]*nodeengine.CandidateAnswer{"anchor": same(7), "laptop": {Proposal: "p-one", Revision: 8,
Verdict: nodeengine.CandidateAnswerVerdictDiffers, Differs: []nodeengine.CandidateDiffers{{Module: "node-tools", Resource: "node-tools.runtime", Why: "the resource differs",
Bodies: []nodeengine.CandidateBodies{{ID: "node-tools.runtime", Paths: []string{"env.MESH_OWNED_PATHS./etc/resolv.conf", "env.MESH_TOOL_MODULES"},
Running: `{"env":{"MESH_OWNED_PATHS":"{\"/etc/hosts\":\"hostname\",\"/etc/resolv.conf\":\"networkmanager (node-uplink)\"}"}}`,
Composed: `{"env":{"MESH_OWNED_PATHS":"{\"/etc/hosts\":\"hostname\",\"/etc/resolv.conf\":\"systemd-resolved (node-resolver)\"}","MESH_TOOL_MODULES":"… (cut at 8192 bytes)`}}}}}}, nil, delivery.VerdictPass, "", ""},
Composed: `{"env":{"MESH_OWNED_PATHS":"{\"/etc/hosts\":\"hostname\",\"/etc/resolv.conf\":\"systemd-resolved (node-resolver)\"}","MESH_TOOL_MODULES":"… (cut at 8192 bytes)`}}}}}}, nil, mdcc.VerdictPass, "", ""},
{"a refusal", false, map[string]*nodeengine.CandidateAnswer{"anchor": same(7), "laptop": {Proposal: "p-one", Revision: 8, Verdict: nodeengine.CandidateAnswerVerdictRefused,
Refusals: []nodeengine.CandidateRefusal{{Module: "web", Why: "no own secret"}}}}, nil, delivery.VerdictFail, "laptop refuses", ""},
Refusals: []nodeengine.CandidateRefusal{{Module: "web", Why: "no own secret"}}}}, nil, mdcc.VerdictFail, "laptop refuses", ""},
{"a node not answering, within its bound", false, map[string]*nodeengine.CandidateAnswer{"anchor": same(7)}, map[string]bool{"laptop": true}, plc.VerdictWaits, "laptop (offline)", ""},
{"an answer of an earlier revision, past its bound, is no answer and decided without it", false, map[string]*nodeengine.CandidateAnswer{"anchor": same(6), "laptop": same(8)}, nil, delivery.VerdictPass, "no answer from anchor", ""},
{"an answer of an earlier revision, past its bound, is no answer and decided without it", false, map[string]*nodeengine.CandidateAnswer{"anchor": same(6), "laptop": same(8)}, nil, mdcc.VerdictPass, "no answer from anchor", ""},
{"a module held as today passes, shown in the brief", false, map[string]*nodeengine.CandidateAnswer{"anchor": same(7), "laptop": {Proposal: "p-one", Revision: 8,
Verdict: nodeengine.CandidateAnswerVerdictSame, Held: []nodeengine.CandidateRefusal{{Module: "spiegel", Why: "a required value is unset"}}}}, nil, delivery.VerdictPass, "", ""},
{"its later answer", false, map[string]*nodeengine.CandidateAnswer{"anchor": same(7), "laptop": same(8)}, nil, delivery.VerdictPass, "", ""},
Verdict: nodeengine.CandidateAnswerVerdictSame, Held: []nodeengine.CandidateRefusal{{Module: "spiegel", Why: "a required value is unset"}}}}, nil, mdcc.VerdictPass, "", ""},
{"its later answer", false, map[string]*nodeengine.CandidateAnswer{"anchor": same(7), "laptop": same(8)}, nil, mdcc.VerdictPass, "", ""},
} {
q := p
q.Seed = row.seed
@@ -73,10 +73,10 @@ func TestJudge(t *testing.T) {
if v.State != row.state || !strings.Contains(all, row.words) {
t.Errorf("%s: %s, %q", row.name, v.State, all)
}
if row.seed && row.state == delivery.VerdictPass && !strings.Contains(Brief(q, v), "the seed carries: node-tools: MESH_OWNED_PATHS[/etc/resolv.conf] networkmanager (node-uplink) → (value cut) (and 1 more fields)") {
if row.seed && row.state == mdcc.VerdictPass && !strings.Contains(Brief(q, v), "the seed carries: node-tools: MESH_OWNED_PATHS[/etc/resolv.conf] networkmanager (node-uplink) → (value cut) (and 1 more fields)") {
t.Errorf("%s: the brief does not name it: %s", row.name, Brief(q, v))
}
if row.seed && row.state == delivery.VerdictPass {
if row.seed && row.state == mdcc.VerdictPass {
whole := row.answers["laptop"].Differs[0]
whole.Bodies = []nodeengine.CandidateBodies{{ID: "r", Paths: []string{"env.MESH_OWNED_PATHS./etc/resolv.conf"},
Running: `{"env":{"MESH_OWNED_PATHS":"{\"/etc/resolv.conf\":\"networkmanager (node-uplink)\"}"}}`,