Files
mesh-controller/internal/conditions/plain_test.go
T
jochen 1fce541023
mesh/merge-gate pass: builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus step; every machine composes with the change as it…
mesh/repo-check fail: its merge-check.sh failed: --- FAIL: TestTheForgesOwnAddressFollowsThePortTheNodeGaveIt (0.00s)
mesh/delivery-group group feat/plain-notifications rejected: a member's own check failed
mesh/delivery superseded: a newer head of the same pull request
Give every condition a headline, an explanation and a resolved line in plain words
The operator could not read the desktop notifications: they carried plan ids,
commits, keys and verb syntax. The words the operator reads now travel with the
condition, so every channel says them (hq ADR 0253).
2026-10-08 13:22:27 +02:00

138 lines
6.2 KiB
Go

package conditions
import (
"encoding/json"
"strings"
"testing"
)
// **The plain rule** (novox/hq ADR 0253): what the operator reads names no identifier, no code and no time
// of its own; the words conditions are made of pass.
func TestThePlainRuleRefusesIdentifiersCodeAndTimes(t *testing.T) {
refused := map[string]string{
"the walk of novox/mesh-catalog a6385479 waits": "a hash",
"plan plan-1791454185265004861 is waiting": "a hash",
"see `mesh-delivery.show` for why": "markup",
"call mesh-delivery.show for why": "a dotted name",
"key plan.x.waiting": "a dotted name",
"waited 56m0s": "a duration in code",
"since 10:40": "a clock time",
"since 2026-10-08": "a clock time",
"raised at noon UTC": "a clock time",
"start it with plans go --why": "a command's flag",
"one line\nand another": "a line break",
"the resolver at 10.77.0.1 is silent": "",
"": "nothing",
"**bold**": "markup",
"storage-media.mount failed": "a dotted name",
"the store at /var/lib/mesh is full": "",
"a commit 0123abc landed": "a hash",
}
for text, want := range refused {
why, ok := Plain(text, "g14")
if ok {
t.Errorf("%q passed", text)
continue
}
if want != "" && !strings.HasPrefix(why, want) {
t.Errorf("%q: refused for %q, want %q", text, why, want)
}
}
for _, text := range []string{
"openrazer delivery waiting to start",
"The change to openrazer is merged and built, and has waited 56 minutes for mesh-delivery to let it start.",
"3 failed services on shanks",
"On shanks, mnt-recalbox (a mount), storage-media (a mount) and greenclip failed.",
"Name lookups fail on g14",
"Retired data of postgres on anchor waits for app_db",
"Push keeps being fixed by hand",
} {
if why, ok := Plain(text, "g14", "shanks", "anchor"); !ok {
t.Errorf("%q refused: %s", text, why)
}
}
}
// **A condition carries its plain words**: a producer's own; else its kind's; else its scope's — and the
// event says them beside the summary, for every channel.
func TestAConditionCarriesItsPlainWords(t *testing.T) {
k, _, told, _ := keeper(t)
before := Unworded
var unworded []string
Unworded = func(o Observation, why string) { unworded = append(unworded, why) }
t.Cleanup(func() { Unworded = before })
Wording("test-silent", func(o Observation) Words {
return Words{Headline: o.Machine + " is not answering", Explanation: "The mesh has not heard from it.",
Resolved: o.Machine + " answers again"}
})
c, err := k.Observe(t.Context(), Observation{Scope: ScopeMachine, ID: "ace", Kind: "test-silent", Machine: "ace",
Severity: Warning, Source: "S1", Summary: "ace has not been heard from since 12:00 UTC (bound 3m0s)"})
if err != nil {
t.Fatal(err)
}
if c.Headline != "ace is not answering" || c.Resolved != "ace answers again" || c.Explanation == "" {
t.Fatalf("the kind's words were not kept: %+v", c)
}
if c.Summary != "ace has not been heard from since 12:00 UTC (bound 3m0s)" {
t.Errorf("the summary was changed: %q", c.Summary)
}
said := settled(t, told, 1)
body, _ := json.Marshal(said[0])
for _, field := range []string{`"headline":"ace is not answering"`, `"explanation":"The mesh has not heard from it."`,
`"resolved":"ace answers again"`} {
if !strings.Contains(string(body), field) {
t.Errorf("the event does not carry %s: %s", field, body)
}
}
// A producer's own words win; a resolved line it leaves out is made from its headline.
c, _ = k.Observe(t.Context(), Observation{Scope: ScopeModule, ID: "openrazer.g14", Kind: "test-silent",
Machine: "g14", Severity: Warning, Source: "health", Summary: "openrazer on g14 is not healthy",
Headline: "openrazer not working on g14", Explanation: "Its service stopped with an error."})
if c.Headline != "openrazer not working on g14" || c.Resolved != "Resolved: openrazer not working on g14" {
t.Errorf("the producer's words: %+v", c)
}
if len(unworded) != 0 {
t.Errorf("words that were plain were reported: %v", unworded)
}
// Words that are not plain, and a kind with none, are said from the scope — and reported.
c, _ = k.Observe(t.Context(), Observation{Scope: ScopeModule, ID: "openrazer.g14", Token: "x", Kind: "test-unworded",
Machine: "g14", Severity: Warning, Source: "health", Summary: "openrazer on g14 is not healthy"})
if c.Headline != "Openrazer on g14 needs a look" || !strings.Contains(c.Explanation, "Nothing to do yet") {
t.Errorf("the scope's words: %+v", c)
}
c, _ = k.Observe(t.Context(), Observation{Scope: ScopePlan, ID: "plan-1791454185265004861", Kind: "test-silent",
Severity: Warning, Source: "S16", Summary: "the walk waits", Headline: "plan-1791454185265004861 waits"})
if strings.Contains(c.Headline, "plan-") || c.Headline != "A walk needs a look" {
t.Errorf("an id reached the headline: %+v", c)
}
if len(unworded) != 2 || !strings.Contains(unworded[0], "no plain words") || !strings.Contains(unworded[1], "not plain") {
t.Errorf("what was said in borrowed words was not reported: %v", unworded)
}
}
// **A healer that gave up says so in the explanation**: the words of the kind said "nothing to do"; once the
// budget is spent, the operator is needed.
func TestAnEscalatedConditionSaysItNeedsTheOperator(t *testing.T) {
k, _, _, _ := keeper(t)
ctx := t.Context()
o := Observation{Scope: ScopeMachine, ID: "ace", Kind: "silent", Machine: "ace", Severity: Warning, Source: "S1",
Summary: "ace is silent", Headline: "ace is not answering", Explanation: "Nothing to do yet."}
if _, err := k.Observe(ctx, o); err != nil {
t.Fatal(err)
}
c, _, err := k.Escalate(ctx, o.Key(), Attempt{What: "budget spent", Outcome: "escalated", By: "healer H1"})
if err != nil {
t.Fatal(err)
}
if !strings.HasSuffix(c.Explanation, Escalated) {
t.Fatalf("escalated: %q", c.Explanation)
}
c, _ = k.Observe(ctx, o)
if strings.Count(c.Explanation, Escalated) != 1 {
t.Errorf("seen again after escalation: %q", c.Explanation)
}
}