mesh/merge-gate pass: builds new: modules/mesh-knowledge, sent nowhere; no bus step; every machine composes with the change as it did without (4 of 4 compo…
mesh/repo-check pass: its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-check-typescript.sh (typescript)
mesh/delivery superseded: a newer head of the same pull request
An agent learns what a decision says only by reading whole records. This module holds every decision record and research effort whole in a database in the store, with clauses that carry their own status and source, typed links read from both ends, and every version. It answers ask, get and holds within a stated bound, and takes a record through reserve, propose (refused on any of the 29 per-record rules), review by someone other than the author, and acceptance, on the operator's proven warrant when the record needs it. The 4 whole-set rules make the module unhealthy when they fail. The import reads hq at a commit through the records module, never overwrites, and changes nothing when run again. Prose decisions get drafted clauses that a second judgement must confirm before they are served.
222 lines
8.7 KiB
Go
222 lines
8.7 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// to-be 55 §10: "A proposal that breaks a per-record rule is refused, naming every reason — the module's table
|
|
// test, one case per rule of §4." Each case takes a proposal every rule takes and breaks one rule; the proposal is
|
|
// refused, the refusal names that rule, and nothing is written. A rule with no case fails the test.
|
|
func TestEveryPerRecordRuleRefusesAProposal(t *testing.T) {
|
|
cases := []struct {
|
|
rule string
|
|
break_ func(p *ProposeAsk, w *world, t *testing.T)
|
|
}{
|
|
{"kind", func(p *ProposeAsk, w *world, t *testing.T) {
|
|
// A kind the verb refuses before the rules: judged by the rules when a record of another kind is held.
|
|
p.Kind = "design"
|
|
}},
|
|
{"reserved", func(p *ProposeAsk, w *world, t *testing.T) { p.Number = 9999 }},
|
|
{"title", func(p *ProposeAsk, w *world, t *testing.T) { p.Title = "two\nlines" }},
|
|
{"topic", func(p *ProposeAsk, w *world, t *testing.T) { p.Topic = "gardening" }},
|
|
{"date", func(p *ProposeAsk, w *world, t *testing.T) { p.Date = "11 October" }},
|
|
{"deciders", func(p *ProposeAsk, w *world, t *testing.T) { p.Deciders = nil }},
|
|
{"research-status", func(p *ProposeAsk, w *world, t *testing.T) {
|
|
p.Kind, p.Number = KindResearch, w.reservedResearch(t)
|
|
p.Status, p.Links = "wondering", nil
|
|
p.Sections = []Section{{Name: "00-overview.md", Text: "An effort."}}
|
|
p.Clauses = nil
|
|
}},
|
|
{"has-clause", func(p *ProposeAsk, w *world, t *testing.T) { p.Clauses = nil; p.Links = p.Links[:1] }},
|
|
{"clause-numbering", func(p *ProposeAsk, w *world, t *testing.T) {
|
|
p.Clauses = []string{"1. **One.** A.", "3. **Three.** C."}
|
|
}},
|
|
{"clause-lead", func(p *ProposeAsk, w *world, t *testing.T) { p.Clauses[1] = "A batch is delivered by one walk." }},
|
|
{"clause-size", func(p *ProposeAsk, w *world, t *testing.T) {
|
|
p.Clauses[1] = "**Long.** " + strings.Repeat("word ", 500)
|
|
}},
|
|
{"context", func(p *ProposeAsk, w *world, t *testing.T) { p.Sections = p.Sections[1:] }},
|
|
{"consequences", func(p *ProposeAsk, w *world, t *testing.T) { p.Sections = append(p.Sections[:2], p.Sections[3]) }},
|
|
{"checked", func(p *ProposeAsk, w *world, t *testing.T) { p.Sections = p.Sections[:3] }},
|
|
{"overview", func(p *ProposeAsk, w *world, t *testing.T) {
|
|
p.Kind, p.Number, p.Status, p.Clauses, p.Links = KindResearch, w.reservedResearch(t), StatusActive, nil, nil
|
|
p.Sections = []Section{{Name: "01-findings.md", Text: "Found."}}
|
|
}},
|
|
{"link-kind", func(p *ProposeAsk, w *world, t *testing.T) {
|
|
p.Links = append(p.Links, LinkAsk{Kind: "admires", To: "0276"})
|
|
}},
|
|
{"link-target", func(p *ProposeAsk, w *world, t *testing.T) {
|
|
p.Links = append(p.Links, LinkAsk{Kind: LinkCites, To: "0007"})
|
|
}},
|
|
{"link-fits", func(p *ProposeAsk, w *world, t *testing.T) {
|
|
p.Links = append(p.Links, LinkAsk{Kind: LinkBecame, To: "0276"})
|
|
}},
|
|
{"self-link", func(p *ProposeAsk, w *world, t *testing.T) {
|
|
p.Links = append(p.Links, LinkAsk{Kind: LinkCites, To: itoa4(p.Number)})
|
|
}},
|
|
{"rests-on", func(p *ProposeAsk, w *world, t *testing.T) {
|
|
p.Links = append(p.Links, LinkAsk{Kind: LinkExtends, To: "0127"})
|
|
}},
|
|
{"supersedes-accepted", func(p *ProposeAsk, w *world, t *testing.T) {
|
|
p.Links = append(p.Links, LinkAsk{Kind: LinkSupersedes, To: "0127"})
|
|
}},
|
|
{"changes-in-force", func(p *ProposeAsk, w *world, t *testing.T) {
|
|
// 0131 superseded 0127, so 0127's clauses are superseded; a changes link to one names a clause no longer in force.
|
|
w.supersededClause(t)
|
|
p.Links = append(p.Links, LinkAsk{Kind: LinkChanges, To: "0011 §1", From: 2})
|
|
}},
|
|
{"live-citation", func(p *ProposeAsk, w *world, t *testing.T) {
|
|
p.Links = append(p.Links, LinkAsk{Kind: LinkCites, To: "0127"})
|
|
}},
|
|
{"became", func(p *ProposeAsk, w *world, t *testing.T) {
|
|
p.Kind, p.Number, p.Status, p.Clauses, p.Links = KindResearch, w.reservedResearch(t), StatusGraduated, nil, nil
|
|
p.Sections = []Section{{Name: "00-overview.md", Text: "An effort that graduated."}}
|
|
}},
|
|
{"text-links", func(p *ProposeAsk, w *world, t *testing.T) {
|
|
p.Sections[0].Text += " See [ADR 0007](0007-a-record-nobody-holds.md)."
|
|
}},
|
|
{"retired-word", func(p *ProposeAsk, w *world, t *testing.T) {
|
|
p.Sections[2].Text = "The control plane is quicker."
|
|
}},
|
|
{"daemon-line", func(p *ProposeAsk, w *world, t *testing.T) {
|
|
p.Sections[3].Text = "Run `mesh-controller doctor` after the merge."
|
|
}},
|
|
{"deferral", func(p *ProposeAsk, w *world, t *testing.T) {
|
|
p.Sections[2].Text = "The bound itself is left for later."
|
|
}},
|
|
{"insight-form", func(p *ProposeAsk, w *world, t *testing.T) {
|
|
p.Sections[2].Text = "A progressive insight corrected the count."
|
|
}},
|
|
}
|
|
covered := map[string]bool{}
|
|
for _, c := range cases {
|
|
covered[c.rule] = true
|
|
}
|
|
for _, r := range PerRecordRules {
|
|
if !covered[r.ID] {
|
|
t.Errorf("the rule %s has no case", r.ID)
|
|
}
|
|
}
|
|
if len(PerRecordRules) != 29 {
|
|
t.Errorf("%d per-record rules; ADR 0290 counts 29", len(PerRecordRules))
|
|
}
|
|
for _, c := range cases {
|
|
t.Run(c.rule, func(t *testing.T) {
|
|
w := imported(t, newMemStore())
|
|
n := w.reserved(t, "author@test")
|
|
p := valid(n)
|
|
c.break_(&p, w, t)
|
|
if c.rule == "kind" {
|
|
// The verb refuses a kind it does not hold before the rules; the rule itself is held by JudgeRecord.
|
|
ref, _ := w.k.reference()
|
|
r := &Record{Kind: "design", Number: n, Title: "x", Date: "2026-10-11"}
|
|
if !names(JudgeRecord(r, mustGet(t, w.k.Store, Key{KindDecision, n}), w.k.lookup(context.Background()), ref), "kind") {
|
|
t.Fatal("a record of an unknown kind was not refused by the kind rule")
|
|
}
|
|
if _, err := w.k.Propose("author@test", p); err == nil {
|
|
t.Fatal("propose took a record of an unknown kind")
|
|
}
|
|
return
|
|
}
|
|
before := versionsOf(t, w, Key{p.Kind, p.Number})
|
|
_, err := w.k.Propose("author@test", p)
|
|
if err == nil {
|
|
t.Fatalf("a proposal breaking %s was taken", c.rule)
|
|
}
|
|
if !strings.Contains(err.Error(), "- "+c.rule+":") {
|
|
t.Fatalf("the refusal does not name %s: %v", c.rule, err)
|
|
}
|
|
if after := versionsOf(t, w, Key{p.Kind, p.Number}); after != before {
|
|
t.Fatalf("a refused proposal wrote a version (%d, was %d)", after, before)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// One proposal breaking three rules is refused naming all three, at once.
|
|
func TestARefusalNamesEveryReasonAtOnce(t *testing.T) {
|
|
w := imported(t, newMemStore())
|
|
p := valid(w.reserved(t, "author@test"))
|
|
p.Topic = "gardening"
|
|
p.Clauses[1] = "no lead here."
|
|
p.Sections[2].Text = "The control plane is quicker."
|
|
_, err := w.k.Propose("author@test", p)
|
|
if err == nil {
|
|
t.Fatal("taken")
|
|
}
|
|
for _, rule := range []string{"topic", "clause-lead", "retired-word"} {
|
|
if !strings.Contains(err.Error(), "- "+rule+":") {
|
|
t.Errorf("the refusal does not name %s: %v", rule, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
// The proposal every case breaks is taken as it is: each case fails for its own rule, not for the base's.
|
|
func TestTheValidProposalIsTaken(t *testing.T) {
|
|
eachStore(t, func(t *testing.T, s Store) {
|
|
w := imported(t, s)
|
|
n := w.reserved(t, "author@test")
|
|
got, err := w.k.Propose("author@test", valid(n))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
e := mustGet(t, s, Key{KindDecision, n})
|
|
if got.Status != StatusProposed || e.Current.Status != StatusProposed || len(e.Current.Clauses) != 2 ||
|
|
e.Current.Clauses[0].Status != ClauseProposed || e.Current.Author != "author@test" {
|
|
t.Fatalf("%+v / %+v", got, e.Current)
|
|
}
|
|
if len(w.said.of(EventProposed)) != 1 || len(w.tracker.asked) != 1 || w.tracker.asked[0]["kind"] != KindDecision {
|
|
t.Fatalf("events %v, tracker %v", w.said.events, w.tracker.asked)
|
|
}
|
|
})
|
|
}
|
|
|
|
func names(refusals []Refusal, rule string) bool {
|
|
for _, r := range refusals {
|
|
if r.Rule == rule {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func versionsOf(t *testing.T, w *world, k Key) int {
|
|
t.Helper()
|
|
e, err := w.k.Store.Get(context.Background(), k)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if e == nil {
|
|
return 0
|
|
}
|
|
return e.Versions
|
|
}
|
|
|
|
func itoa4(n int) string { return fmt.Sprintf("%04d", n) }
|
|
|
|
func (w *world) reservedResearch(t *testing.T) int {
|
|
t.Helper()
|
|
r, err := w.k.ReserveNumber("author@test", KindResearch, "a test effort")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return r.Number
|
|
}
|
|
|
|
// supersededClause gives 0011, accepted, one clause a later record superseded, so a change to that clause names
|
|
// one no longer in force.
|
|
func (w *world) supersededClause(t *testing.T) {
|
|
t.Helper()
|
|
ctx := context.Background()
|
|
e := mustGet(t, w.k.Store, Key{KindDecision, 11})
|
|
r := e.Current.Clone()
|
|
r.Clauses = []Clause{{N: 1, Text: "**Generated.** Managed files are generated.", Status: ClauseSuperseded, Source: SourceWritten,
|
|
ChangedBy: []string{"ADR 0012"}}}
|
|
if err := w.k.Store.Save(ctx, Version{By: "test", Why: "superseded for the test", Record: r}, true, false, e.Revision); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|