mesh-knowledge: refresh repairs records the knowledge base drafted, keeping their clauses while their source is unchanged; ADR 0114 and 0148 as fixtures (review of #213)
mesh/merge-gate pass: builds mesh-knowledge → novox; no bus step; every machine composes with the change as it did without (4 of 4 compose)
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 covered: a later merge that contains it was delivered: novox/mesh-catalog@1b7f79f76177 (merged as 73367192 into main, walk plan-17917161183…
mesh/merge-gate pass: builds mesh-knowledge → novox; no bus step; every machine composes with the change as it did without (4 of 4 compose)
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 covered: a later merge that contains it was delivered: novox/mesh-catalog@1b7f79f76177 (merged as 73367192 into main, walk plan-17917161183…
This commit is contained in:
@@ -24,7 +24,7 @@ func imported487(t *testing.T, s Store) *world {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if out.Refused != 0 || out.Created != 13 {
|
||||
if out.Refused != 0 || out.Created != 15 {
|
||||
t.Fatalf("%s %+v", out.Said, out.Rows)
|
||||
}
|
||||
return w
|
||||
@@ -107,7 +107,7 @@ func TestTheImportHoldsEveryFieldOfARecord(t *testing.T) {
|
||||
func TestClausesComeOnlyFromTheDecisionSectionsOwnList(t *testing.T) {
|
||||
eachStore(t, func(t *testing.T, s Store) {
|
||||
imported487(t, s)
|
||||
for _, n := range []int{259, 272, 273, 278, 288, 40} {
|
||||
for _, n := range []int{259, 272, 273, 278, 288, 40, 114, 148} {
|
||||
r := mustGet(t, s, Key{KindDecision, n}).Current
|
||||
if len(r.Clauses) != 0 || r.Drafting == nil || r.Drafting.State != DraftWaiting {
|
||||
t.Errorf("ADR %04d: %d clause(s) %v, drafting %+v", n, len(r.Clauses), r.Clauses, r.Drafting)
|
||||
@@ -254,12 +254,11 @@ func TestARefreshRepairsOnlyRecordsNobodyChangedSinceTheImportAndChangesNothingT
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
// ADR 0085 was drafted since its import: someone changed it, and the refresh never touches it.
|
||||
// ADR 0085 was corrected by someone since its import, and the refresh never touches it.
|
||||
e85 := mustGet(t, s, Key{KindDecision, 85})
|
||||
d := e85.Current.Clone()
|
||||
d.Clauses = []Clause{{N: 1, Text: "**Secret-holding is a module.** It is.", Status: ClauseInForce, Source: SourceDrafted}}
|
||||
d.Drafting = &Drafting{State: DraftDrafted}
|
||||
if err := s.Save(ctx, Version{By: "the agent on test (sonnet)", At: at, Why: "1 clauses drafted", Record: d}, true, false, e85.Revision); err != nil {
|
||||
d.Title = "A secret is a provision, corrected"
|
||||
if err := s.Save(ctx, Version{By: "someone@g14", At: at, Why: "a correction by hand", Record: d}, true, false, e85.Revision); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
before := countVersions(t, s)
|
||||
@@ -269,7 +268,7 @@ func TestARefreshRepairsOnlyRecordsNobodyChangedSinceTheImportAndChangesNothingT
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if countVersions(t, s) != before || dry.Refreshed != 12 || dry.ChangedSince != 1 || dry.Created != 0 {
|
||||
if countVersions(t, s) != before || dry.Refreshed != 14 || dry.ChangedSince != 1 || dry.Created != 0 {
|
||||
t.Fatalf("dry run: %s", dry.Said)
|
||||
}
|
||||
says := map[string]ImportRow{}
|
||||
@@ -290,7 +289,7 @@ func TestARefreshRepairsOnlyRecordsNobodyChangedSinceTheImportAndChangesNothingT
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if out.Refreshed != 12 || out.ChangedSince != 1 || countVersions(t, s) != before+12 {
|
||||
if out.Refreshed != 14 || out.ChangedSince != 1 || countVersions(t, s) != before+14 {
|
||||
t.Fatalf("refresh: %s", out.Said)
|
||||
}
|
||||
e := mustGet(t, s, Key{KindDecision, 259})
|
||||
@@ -308,7 +307,7 @@ func TestARefreshRepairsOnlyRecordsNobodyChangedSinceTheImportAndChangesNothingT
|
||||
if r := mustGet(t, s, Key{KindResearch, 21}).Current; len(r.Touches) != 4 {
|
||||
t.Fatalf("research 021 not repaired: %v", r.Touches)
|
||||
}
|
||||
if e := mustGet(t, s, Key{KindDecision, 85}); e.Versions != 2 || len(e.Current.Clauses) != 1 {
|
||||
if e := mustGet(t, s, Key{KindDecision, 85}); e.Versions != 2 || e.Current.Title != "A secret is a provision, corrected" {
|
||||
t.Fatalf("0085, changed since its import, was touched: %d versions", e.Versions)
|
||||
}
|
||||
// Run again: nothing changes, and it says so.
|
||||
@@ -317,22 +316,81 @@ func TestARefreshRepairsOnlyRecordsNobodyChangedSinceTheImportAndChangesNothingT
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if again.Refreshed != 0 || again.Unchanged != 12 || countVersions(t, s) != after || !strings.Contains(again.Said, "Nothing changed") {
|
||||
if again.Refreshed != 0 || again.Unchanged != 14 || countVersions(t, s) != after || !strings.Contains(again.Said, "Nothing changed") {
|
||||
t.Fatalf("a second refresh: %s", again.Said)
|
||||
}
|
||||
// Once drafted, a repaired record is someone's: a later refresh leaves it alone.
|
||||
draftUntil(t, w, Key{KindDecision, 259}, DraftDone)
|
||||
// Drafted and confirmed since, by the knowledge base itself: still the import's side. A later refresh keeps
|
||||
// the drafted clauses, since the Decision section they come from is unchanged, and changes nothing.
|
||||
r259 := draftUntil(t, w, Key{KindDecision, 259}, DraftDone)
|
||||
third, _ := w.k.Import("import@test", ImportAsk{Refresh: true}, at487())
|
||||
changed := false
|
||||
for _, row := range third.Rows {
|
||||
changed = changed || (row.Record == "ADR 0259" && row.Action == ImportChangedSince)
|
||||
if row.Record == "ADR 0259" {
|
||||
t.Fatalf("0259 in a third refresh: %+v", row)
|
||||
}
|
||||
}
|
||||
if third.Refreshed != 0 || !changed || mustGet(t, s, Key{KindDecision, 259}).Current.Drafting.State != DraftDone {
|
||||
if got := mustGet(t, s, Key{KindDecision, 259}).Current; third.Refreshed != 0 || renderJSON(got.Clauses) != renderJSON(r259.Clauses) {
|
||||
t.Fatalf("a third refresh: %s", third.Said)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Live, ADR 0002 has versions 2 and 3 drafted and confirmed by the knowledge base after its import. Those are the
|
||||
// import's side: a refresh repairs it, keeping its clauses while the Decision section they were drafted from is
|
||||
// what hq says, and queuing it to be drafted again when it is not.
|
||||
func TestARefreshRepairsARecordTheKnowledgeBaseDraftedAndKeepsItsClauses(t *testing.T) {
|
||||
eachStore(t, func(t *testing.T, s Store) {
|
||||
ctx := context.Background()
|
||||
w := newWorld(t, s, at487())
|
||||
commit, _ := at487().Standing()
|
||||
p2 := DecisionsFolder + "/0002-nodes-communicate-over-a-broker.md"
|
||||
p4 := DecisionsFolder + "/0004-a-node-and-how-it-joins.md"
|
||||
r2 := legacy(t, p2, commit)
|
||||
// 0004 has no Decision section; the import before #487 queued nothing, so a hand-made drafting stands in for
|
||||
// one made from a text that is no longer what hq says.
|
||||
r4 := legacy(t, p4, commit)
|
||||
r4.Drafting = &Drafting{State: DraftWaiting}
|
||||
r4.Sections = append(r4.Sections, Section{Name: "Decision", Text: "Nodes join by a token. That is decided here."})
|
||||
for _, c := range []struct {
|
||||
path string
|
||||
r *Record
|
||||
}{{p2, r2}, {p4, r4}} {
|
||||
if err := s.Create(ctx, Version{By: Unproven, Why: "imported from hq at " + short(commit) + ": " + c.path, Record: c.r}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
drafted2 := draftUntil(t, w, Key{KindDecision, 2}, DraftDone)
|
||||
draftUntil(t, w, Key{KindDecision, 4}, DraftDone)
|
||||
if mustGet(t, s, Key{KindDecision, 2}).Versions != 3 {
|
||||
t.Fatal("0002 was not drafted and confirmed as live")
|
||||
}
|
||||
out, err := w.k.Import("import@test", ImportAsk{Refresh: true}, at487())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if out.ChangedSince != 0 {
|
||||
t.Fatalf("drafting counted as a change: %s %+v", out.Said, out.Rows)
|
||||
}
|
||||
e2 := mustGet(t, s, Key{KindDecision, 2})
|
||||
if e2.Versions != 4 || e2.Current.Reconstructed == nil || !*e2.Current.Reconstructed ||
|
||||
renderJSON(e2.Current.Clauses) != renderJSON(drafted2.Clauses) || e2.Current.Drafting == nil || e2.Current.Drafting.State != DraftDone {
|
||||
t.Fatalf("0002 after the refresh: %d versions, %+v, drafting %+v", e2.Versions, e2.Current.Clauses, e2.Current.Drafting)
|
||||
}
|
||||
// 0004's clauses were drafted from a text hq does not hold: taken back, and drafted again from its sections.
|
||||
e4 := mustGet(t, s, Key{KindDecision, 4}).Current
|
||||
if len(e4.Clauses) != 0 || e4.Drafting == nil || e4.Drafting.State != DraftWaiting || !strings.Contains(e4.Drafting.Reason, "no Decision section") {
|
||||
t.Fatalf("0004 after the refresh: %+v %+v", e4.Clauses, e4.Drafting)
|
||||
}
|
||||
// A record someone returned is someone's change: left alone.
|
||||
if _, err := w.k.Return("operator@shanks", Key{KindDecision, 2}, "clause 2 says more than the record"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
again, _ := w.k.Import("import@test", ImportAsk{Refresh: true}, at487())
|
||||
if again.ChangedSince != 1 {
|
||||
t.Fatalf("a returned record refreshed: %s", again.Said)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// A refresh without a commit's records refuses, and an import without refresh never rewrites what it holds.
|
||||
func TestAnImportWithoutRefreshLeavesAHeldRecordAsItIs(t *testing.T) {
|
||||
w := newWorld(t, newMemStore(), at487())
|
||||
|
||||
Reference in New Issue
Block a user