K22 (finding helpers gone): meshconditionsclient keeps what concerns conditions, and heard builds the seat's generated finding

The helpers CheckFinding, FindingFor, FindingWriter, FindingState, FindingVersion, Observation, EncodeFinding, DecodeFinding, Says,
FindingBucket, FindingsBucket, Raise, Clear and CallUnanswered go; mesh-sdk's writer is the one writer and checks. Importers
outside this repository move in G's change (named in the line).

Builds: design 47 G §689 (§461, §503, §640, §660)

Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
This commit is contained in:
2026-11-11 20:43:22 +01:00
parent 74b6162807
commit b2cc72b4a3
8 changed files with 31 additions and 406 deletions
@@ -0,0 +1,11 @@
package meshconditionsclient
import "time"
// KindCallUnanswered is the kind of a kept call still unanswered past CallUnansweredAfter (novox/hq ADR 0668 §3, issue
// 1966): a call whose answer the caller keeps, asked again through every transport fault, that no answer has ended. The
// caller writes it into its own findings, keeps the wait, and clears it when the call is answered.
const KindCallUnanswered = "call-unanswered"
// CallUnansweredAfter is how long a kept call stays unanswered before it is a finding (ADR 0668 §3; ADR 0564 §2's bound).
const CallUnansweredAfter = 5 * time.Minute
@@ -1,17 +1,15 @@
// Package meshconditionsclient is the logic every observer, healer and reader of conditions shares over the seat
// mesh-conditions (novox/hq ADR 0564, ADR 0634 §4): how a finding's key is made and checked, the scopes and the bounds,
// mesh-conditions (novox/hq ADR 0564, ADR 0634 §4): how a finding's key is made, the scopes and the bounds,
// the order a person reads conditions in, and the answers a notification offers. The layouts are the seat's contract's.
package meshconditionsclient
import (
"fmt"
"regexp"
"sort"
"strings"
"time"
seat "git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshconditions"
"git.novox.be/novox/mesh-sdk/go/views"
)
// The two severities, how soon the operator is needed.
@@ -111,39 +109,6 @@ func SilenceAction(key string) seat.Action {
Arguments: map[string]string{"key": key, "for": "7d", "why": "", "cause": CauseOperatorAnswer}}
}
// CheckFinding refuses a finding the keeper could not make a condition of, naming why.
func CheckFinding(f seat.FindingsByKeyValue) error {
known := false
for _, s := range Scopes {
known = known || s == f.Subject.Scope
}
token := f.Ref
if token == "" {
token = f.Kind
}
switch {
case !known:
return fmt.Errorf("health: a finding's scope is one of %s, not %q", strings.Join(Scopes, ", "), f.Subject.Scope)
case strings.TrimSpace(f.Subject.ID) == "":
return fmt.Errorf("health: a %s finding names what it is about", f.Subject.Scope)
case strings.TrimSpace(f.Kind) == "":
return fmt.Errorf("health: the finding %s has no kind", f.Key)
case f.Key != Key(f.Subject.Scope, f.Subject.ID, token):
return fmt.Errorf("health: the finding's key %q is not %q, its scope, id and kind", f.Key, Key(f.Subject.Scope, f.Subject.ID, token))
case f.Severity != Urgent && f.Severity != Warning:
return fmt.Errorf("health: the finding %s is urgent or a warning, not %q", f.Key, f.Severity)
case strings.TrimSpace(f.Summary) == "":
return fmt.Errorf("health: the finding %s says nothing", f.Key)
case strings.TrimSpace(f.Source) == "":
return fmt.Errorf("health: the finding %s does not say what saw it", f.Key)
case strings.TrimSpace(f.Observer) == "":
return fmt.Errorf("health: the finding %s does not name its observer", f.Key)
case len(f.Evidence) > KeptEvidence:
return fmt.Errorf("health: the finding %s keeps %d observations, at most %d", f.Key, len(f.Evidence), KeptEvidence)
}
return nil
}
// Order sorts conditions as a person reads them: urgent first, then oldest raised, then by key.
func Order(list []seat.ConditionsByKeyValue) {
raised := func(c seat.ConditionsByKeyValue) time.Time { return c.Raised }
@@ -171,44 +136,3 @@ func SilencedAt(c seat.ConditionsByKeyValue, now time.Time) bool {
func Escalated(c seat.ConditionsByKeyValue) bool {
return c.Resolver == ResolverOperator && len(c.Tried) > 0
}
// FindingVersion is the layout version of a finding's value.
const FindingVersion = 1
// FindingState is a part's own state `findings`, where the condition keeper reads what a part saw: the runtime's kept
// state (mesh-sdk's KeptState) satisfies it.
type FindingState interface {
Put(key string, value any) (uint64, error)
Delete(key string) error
}
// FindingWriter writes and clears a part's findings of a module in its own state `findings`, in this seat's layout; it
// is mesh-sdk's views.FindingWriter. A finding is a warning about the module its ID names, and is checked
// (CheckFinding) before it is written.
type FindingWriter struct{ State FindingState }
var _ views.FindingWriter = FindingWriter{}
// FindingFor is the value and key of the seat's finding for f.
func FindingFor(f views.Finding) seat.FindingsByKeyValue {
at := f.At.UTC()
return seat.FindingsByKeyValue{V: FindingVersion, Key: Key(ScopeModule, f.ID, f.Kind), Kind: f.Kind,
Subject: seat.Subject{Scope: ScopeModule, ID: f.ID}, Severity: Warning, Summary: f.Summary, Headline: f.Headline,
Explanation: f.Explanation, Evidence: []seat.Evidence{{At: at, Said: f.Summary}}, Source: f.Observer + "." + f.Kind,
Observer: f.Observer, At: at}
}
// Put writes the finding.
func (w FindingWriter) Put(f views.Finding) error {
v := FindingFor(f)
if err := CheckFinding(v); err != nil {
return err
}
_, err := w.State.Put(v.Key, v)
return err
}
// Delete clears the finding.
func (w FindingWriter) Delete(f views.Finding) error {
return w.State.Delete(Key(ScopeModule, f.ID, f.Kind))
}
@@ -1,14 +1,10 @@
package meshconditionsclient
import (
"os"
"reflect"
"strings"
"testing"
"time"
seat "git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshconditions"
"git.novox.be/novox/mesh-sdk/go/views"
)
// ADR 0564 clause 3: the key rule, the checks of a finding, the order and the silence a person reads conditions by.
@@ -19,33 +15,8 @@ func TestAFindingsKeyAndTheOrderOfConditions(t *testing.T) {
if k := Key("call", "a b", ""); k != "call.a_b._" {
t.Errorf("an unsafe part and an empty token: %s", k)
}
// Issue 1966, ADR 0668 §3: a kept call unanswered is a finding the keeper can make a condition of, keyed by what waits.
o := CallUnanswered("ace", "seat:node-engine.manifest-reads", "ace", "no responders", "enginereads", time.Unix(0, 0))
if f := o.Finding("mesh-delivery-assigner", "r1", time.Unix(300, 0)); o.Key() != "call.ace.call-unanswered" || CheckFinding(f) != nil {
t.Errorf("a call unanswered: key %s, %v", o.Key(), CheckFinding(f))
}
good := seat.FindingsByKeyValue{Key: "machine.g14.silent", Kind: "silent", Severity: Warning, Summary: "x", Source: "S1",
Observer: "mesh-delivery-watchman", Subject: seat.Subject{Scope: ScopeMachine, ID: "g14"}}
for _, c := range []struct {
name string
change func(*seat.FindingsByKeyValue)
refuse string
}{
{"a good finding", func(*seat.FindingsByKeyValue) {}, ""},
{"an unknown scope", func(f *seat.FindingsByKeyValue) { f.Subject.Scope = "moon" }, "scope is one of"},
{"a key that is not its subject's", func(f *seat.FindingsByKeyValue) { f.Key = "machine.g14.other" }, "is not"},
{"a reference as the key's last part", func(f *seat.FindingsByKeyValue) { f.Ref = "gone"; f.Key = "machine.g14.gone" }, ""},
{"no summary", func(f *seat.FindingsByKeyValue) { f.Summary = " " }, "says nothing"},
{"no observer", func(f *seat.FindingsByKeyValue) { f.Observer = "" }, "observer"},
{"a severity of neither kind", func(f *seat.FindingsByKeyValue) { f.Severity = "info" }, "urgent or a warning"},
{"too much evidence", func(f *seat.FindingsByKeyValue) { f.Evidence = make([]seat.Evidence, KeptEvidence+1) }, "keeps 11"},
} {
f := good
c.change(&f)
err := CheckFinding(f)
if (c.refuse == "") != (err == nil) || (err != nil && !strings.Contains(err.Error(), c.refuse)) {
t.Errorf("%s: %v", c.name, err)
}
if KindCallUnanswered != "call-unanswered" || CallUnansweredAfter != 5*time.Minute {
t.Error("the kept call's finding kind and bound")
}
list := []seat.ConditionsByKeyValue{
{Key: "b", Severity: Warning, Raised: when("2026-11-01T10:00:00Z")},
@@ -69,44 +40,6 @@ func TestAFindingsKeyAndTheOrderOfConditions(t *testing.T) {
}
}
type fakeFindings struct {
put map[string]any
deleted []string
}
func (f *fakeFindings) Put(key string, value any) (uint64, error) {
if f.put == nil {
f.put = map[string]any{}
}
f.put[key] = value
return 1, nil
}
func (f *fakeFindings) Delete(key string) error { f.deleted = append(f.deleted, key); return nil }
func TestTheFindingWriterWritesAndClearsAModulesFindingInTheSeatsLayout(t *testing.T) {
state := &fakeFindings{}
var w views.FindingWriter = FindingWriter{State: state}
f := views.Finding{Observer: "mesh-config", Kind: "unanswered", ID: "mesh-config.mesh-vault.secrets", Summary: "no first view",
Headline: "waits", Explanation: "look", At: time.Date(2026, 11, 5, 12, 0, 0, 0, time.UTC)}
if err := w.Put(f); err != nil {
t.Fatal(err)
}
key := "module.mesh-config.mesh-vault.secrets.unanswered"
v, ok := state.put[key].(seat.FindingsByKeyValue)
if !ok || v.Key != key || v.Severity != Warning || v.Source != "mesh-config.unanswered" || v.Subject.Scope != ScopeModule || len(v.Evidence) != 1 {
t.Fatalf("written %#v", state.put)
}
if err := CheckFinding(v); err != nil {
t.Error(err)
}
if err := w.Delete(f); err != nil || len(state.deleted) != 1 || state.deleted[0] != key {
t.Errorf("deleted %v: %v", state.deleted, err)
}
if err := w.Put(views.Finding{Observer: "x", Kind: "k", ID: "i"}); err == nil {
t.Error("a finding that says nothing was written")
}
}
func when(s string) time.Time {
t, err := time.Parse(time.RFC3339Nano, s)
if err != nil {
@@ -116,85 +49,3 @@ func when(s string) time.Time {
}
func ptr(t time.Time) *time.Time { return &t }
type fakeBucket struct {
kept map[string][]byte
puts, dels int
}
func (b *fakeBucket) Get(key string) ([]byte, bool, error) { v, ok := b.kept[key]; return v, ok, nil }
func (b *fakeBucket) Put(key string, v []byte) error {
if b.kept == nil {
b.kept = map[string][]byte{}
}
b.kept[key] = v
b.puts++
return nil
}
func (b *fakeBucket) Delete(key string) error { delete(b.kept, key); b.dels++; return nil }
// The goldens are what mesh-sdk's go/health EncodeFinding wrote for the same findings: the helpers write the same
// values, read by the seat's strict decoder.
func TestAnObservationIsWrittenAsMeshSDKsHealthWroteItsFinding(t *testing.T) {
at := time.Date(2026, 11, 5, 12, 0, 0, 0, time.UTC)
for _, c := range []struct {
golden string
o Observation
run string
}{
{"finding_full.json", Observation{Scope: ScopeMachine, ID: "g14", Kind: "silent-kind", Ref: "silent", Machine: "g14", Also: []string{"ace"},
Severity: Urgent, Summary: "g14 is silent", Said: "no pulse", Headline: "g14 is silent", Explanation: "It said nothing.",
Resolved: "It speaks.", Needs: "look", Source: "S1", Resolver: "operator"}, "r1"},
{"finding_minimal.json", Observation{Scope: ScopeModule, ID: "nats.g14", Kind: "build-failed", Summary: "failed",
Source: "builder.build-failed"}, ""},
} {
raw, err := os.ReadFile("testdata/" + c.golden)
if err != nil {
t.Fatal(err)
}
want, err := seat.DecodeFindingsByKeyValue(raw)
if err != nil {
t.Fatalf("%s: %v", c.golden, err)
}
observer := want.Observer
got, err := EncodeFinding(c.o.Finding(observer, c.run, at))
if err != nil {
t.Fatalf("%s: %v", c.golden, err)
}
have, err := seat.DecodeFindingsByKeyValue(got)
if err != nil || !reflect.DeepEqual(have, want) {
t.Errorf("%s: wrote %s, want %s (%v)", c.golden, got, raw, err)
}
if back, err := DecodeFinding(raw); err != nil || !reflect.DeepEqual(back, want) {
t.Errorf("%s: read back %v", c.golden, err)
}
}
}
func TestRaiseWritesWhenTheWordsChangeAndClearDeletesWhatIsThere(t *testing.T) {
b := &fakeBucket{}
o := Observation{Scope: ScopeModule, ID: "m", Kind: "k", Summary: "one", Source: "x.k"}
at := when("2026-11-05T12:00:00Z")
if w, err := Raise(b, "obs", "", o, at); err != nil || !w {
t.Fatalf("first: %v %v", w, err)
}
if w, err := Raise(b, "obs", "r2", o, at.Add(time.Hour)); err != nil || w || b.puts != 1 {
t.Fatalf("the same words later: wrote %v, %d puts, %v", w, b.puts, err)
}
o.Summary = "two"
if w, err := Raise(b, "obs", "", o, at); err != nil || !w || b.puts != 2 {
t.Fatalf("changed: %v %d %v", w, b.puts, err)
}
if _, err := Raise(b, "obs", "", Observation{Scope: "moon", ID: "m", Kind: "k"}, at); err == nil || b.puts != 2 {
t.Errorf("a finding the keeper cannot use was written: %v", err)
}
if c, err := Clear(b, ScopeModule, "m", "k"); err != nil || !c || b.dels != 1 {
t.Fatalf("clear: %v %v %d", c, err, b.dels)
}
if c, err := Clear(b, ScopeModule, "m", "k"); err != nil || c || b.dels != 1 {
t.Errorf("clearing what is not there: %v %v %d", c, err, b.dels)
}
if FindingsBucket("obs") != "obs_findings" {
t.Error(FindingsBucket("obs"))
}
}
@@ -13,7 +13,7 @@ import (
"time"
"git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshconditionsclient"
"git.novox.be/novox/mesh-sdk/go/views"
seat "git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshconditions"
)
// Kind is the finding's kind.
@@ -43,16 +43,18 @@ func Words(observer, family, consequence string, why error) (summary, headline,
return summary, headline, explanation
}
// Finding is observer's finding that it does not hear family, in the layout of the seat mesh-conditions' state findings.
// Finding is observer's finding that it does not hear family, as the seat mesh-conditions' generated type
// (design 47 G 689): its key and its value. The check of its rules is mesh-sdk's writer's, which refuses a finding
// breaking them before it writes.
func Finding(observer, family, consequence string, why error, at time.Time) (string, []byte, error) {
summary, headline, explanation := Words(observer, family, consequence, why)
v := meshconditionsclient.FindingFor(views.Finding{Observer: observer, Kind: Kind, ID: ID(observer, family), Summary: summary,
Headline: headline, Explanation: explanation, At: at})
if err := meshconditionsclient.CheckFinding(v); err != nil {
return v.Key, nil, err
}
at = at.UTC()
v := seat.Finding{Scope: meshconditionsclient.ScopeModule, ID: ID(observer, family), Kind: Kind,
Subject: seat.Subject{Scope: meshconditionsclient.ScopeModule, ID: ID(observer, family)},
Severity: meshconditionsclient.Warning, Summary: summary, Headline: headline, Explanation: explanation,
Evidence: []seat.Evidence{{At: at, Said: summary}}, Source: observer + "." + Kind, Observer: observer, At: at, Since: at}
value, err := json.Marshal(v)
return v.Key, value, err
return Key(observer, family), value, err
}
// Writer writes and deletes the finding in the observer's findings state. Put or Delete nil writes nothing, said in the
@@ -5,6 +5,8 @@ import (
"strings"
"testing"
"time"
seat "git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshconditions"
)
// A consumer that does not bind writes the finding, with why, under the observer's findings key; the one that binds
@@ -22,6 +24,11 @@ func TestBindWritesTheFindingUntilTheConsumerBinds(t *testing.T) {
if err := w.Bind("placement", "the first view is the only picture", func() error { return errors.New("no consumer") }); err == nil {
t.Fatal("a failed bind was not answered")
}
// Design 47 G 689: the value is the seat's generated finding, read by its strict decoder, key and subject by the rule.
if f, err := seat.DecodeFindingsByScopeIDKindValue(puts[key]); err != nil || f.Observer != "mesh-x" || f.Kind != Kind ||
f.Scope != "module" || f.ID != "mesh-x.placement" || f.Subject.ID != f.ID || f.Severity != "warning" || f.Source == "" {
t.Errorf("the finding is not the seat's generated one: %+v (%v)", f, err)
}
if v := string(puts[key]); !strings.Contains(v, "no consumer") || !strings.Contains(v, "mesh-x does not hear placement") {
t.Errorf("the finding is %q", v)
}
@@ -1,168 +0,0 @@
package meshconditionsclient
import (
"encoding/json"
"fmt"
"time"
seat "git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshconditions"
)
// What an observer says it sees wrong, raised and cleared as a finding in its own state `findings` (novox/hq ADR 0564
// clause 2, ADR 0634 §4): one write shared by every observer (the self-check, the healers, the watchman, the builder,
// the indexer, the node-engine), in this seat's layout. The condition keeper raises and clears the conditions from them.
// FindingsState is the name of an observer's state of findings.
const FindingsState = "findings"
// FindingsBucket is the bucket of an observer's findings, `<module>_findings`.
func FindingsBucket(observer string) string { return observer + "_" + FindingsState }
// Observation is one thing an observer sees wrong now: what it is about (Scope, ID, Machine, Also), which kind of fault
// (Kind; Ref when the key's last part is not the kind), and its words.
type Observation struct {
Scope, ID, Kind, Ref, Machine string
Also []string
// Severity is Urgent or Warning; Warning when empty.
Severity string
// Summary is one line; Said the one observation kept as evidence (the summary when empty).
Summary, Said string
Headline, Explanation, Resolved, Needs string
// Source is the row, probe or event that saw it.
Source string
// Resolver is who resolves it, self when empty.
Resolver string
Actions []seat.Action
// Since is when the finding is stamped; the zero value leaves it to the caller's moment.
Since time.Time
}
// Key is the finding's key: `<scope>.<id>.<token>`, the token Ref or else Kind.
func (o Observation) Key() string {
token := o.Ref
if token == "" {
token = o.Kind
}
return Key(o.Scope, o.ID, token)
}
// Finding is the observation as the seat's finding written by observer in run, at the moment at.
func (o Observation) Finding(observer, run string, at time.Time) seat.FindingsByKeyValue {
at = at.UTC()
said := o.Said
if said == "" {
said = o.Summary
}
sev := o.Severity
if sev == "" {
sev = Warning
}
f := seat.FindingsByKeyValue{V: FindingVersion, Key: o.Key(), Kind: o.Kind,
Subject: seat.Subject{Scope: o.Scope, ID: o.ID, Machine: o.Machine, Also: o.Also},
Severity: sev, Summary: o.Summary, Headline: o.Headline, Explanation: o.Explanation, Resolved: o.Resolved,
Needs: o.Needs, Actions: o.Actions, Evidence: []seat.Evidence{{At: at, Said: said}}, Source: o.Source,
Resolver: o.Resolver, Observer: observer, Run: run, At: at}
if o.Ref != "" && o.Ref != o.Kind {
f.Ref = o.Ref
}
return f
}
// EncodeFinding is f as JSON at FindingVersion; it refuses what CheckFinding refuses.
func EncodeFinding(f seat.FindingsByKeyValue) ([]byte, error) {
f.V = FindingVersion
if f.Evidence == nil {
f.Evidence = []seat.Evidence{}
}
if err := CheckFinding(f); err != nil {
return nil, err
}
return json.Marshal(f)
}
// DecodeFinding reads a finding's value; it refuses another version and what CheckFinding refuses. A finding written
// before the field was named `ref` (novox/hq issue 1952) is read by its old name, `token`.
func DecodeFinding(data []byte) (seat.FindingsByKeyValue, error) {
f, err := seat.DecodeFindingsByKeyValue(data)
if err != nil {
return seat.FindingsByKeyValue{}, fmt.Errorf("health: a finding is not readable: %w", err)
}
if f.V != FindingVersion {
return seat.FindingsByKeyValue{}, fmt.Errorf("health: a finding of version %d, and this reads %d", f.V, FindingVersion)
}
if err := CheckFinding(f); err != nil {
return seat.FindingsByKeyValue{}, err
}
return f, nil
}
// Says is what a finding says, the moments and the run that wrote it aside: two findings that say the same are one
// write (novox/hq ADR 0289 §1), so the condition moves only when the words do.
func Says(f seat.FindingsByKeyValue) string {
f.At, f.Run, f.V = time.Time{}, "", 0
ev := make([]seat.Evidence, len(f.Evidence))
for i, e := range f.Evidence {
ev[i] = seat.Evidence{Said: e.Said}
}
f.Evidence = ev
raw, _ := json.Marshal(f)
return string(raw)
}
// FindingBucket is the part of an observer's state `findings` that Raise and Clear use.
type FindingBucket interface {
// Get answers the value at key; found is false when there is none.
Get(key string) (value []byte, found bool, err error)
Put(key string, value []byte) error
Delete(key string) error
}
// Raise writes the observation as observer's finding in run at at, only when what it says differs from the finding kept
// (so the keeper's condition moves only then); wrote says whether it wrote. A finding the keeper could not make a
// condition of is refused, nothing written.
func Raise(b FindingBucket, observer, run string, o Observation, at time.Time) (wrote bool, err error) {
f := o.Finding(observer, run, at)
value, err := EncodeFinding(f)
if err != nil {
return false, err
}
if kept, found, err := b.Get(f.Key); err != nil {
return false, err
} else if found {
if old, err := DecodeFinding(kept); err == nil && Says(old) == Says(f) {
return false, nil
}
}
return true, b.Put(f.Key, value)
}
// Clear deletes the finding about scope and id of kind (its token); one not there is nothing to clear, and cleared says
// whether one was.
func Clear(b FindingBucket, scope, id, token string) (cleared bool, err error) {
key := Key(scope, id, token)
if _, found, err := b.Get(key); err != nil || !found {
return false, err
}
return true, b.Delete(key)
}
// KindCallUnanswered is the kind of a kept call still unanswered past CallUnansweredAfter (novox/hq ADR 0668 §3, issue
// 1966): a call whose answer the caller keeps, asked again through every transport fault, that no answer has ended. The
// caller writes it into its own findings, keeps the wait, and clears it when the call is answered.
const KindCallUnanswered = "call-unanswered"
// CallUnansweredAfter is how long a kept call stays unanswered before it is a finding (ADR 0668 §3; ADR 0564 §2's bound).
const CallUnansweredAfter = 5 * time.Minute
// CallUnanswered is the observation of a kept call to callee (a seat verb's or a tool's key, as process.Conn.Call names
// it) about id (what the caller waits on: a node, a merge, a key), unanswered since since, its last fault said. Its key
// is `call.<id>.call-unanswered`, cleared by Clear(b, ScopeCall, id, KindCallUnanswered).
func CallUnanswered(id, callee, machine, fault, source string, since time.Time) Observation {
return Observation{Scope: ScopeCall, ID: id, Kind: KindCallUnanswered, Machine: machine, Severity: Warning,
Summary: fmt.Sprintf("the call %s about %s is unanswered since %s", callee, id, since.UTC().Format(time.RFC3339)),
Said: fault,
Headline: "A call whose answer is kept is not answered",
Explanation: fmt.Sprintf("The call %s is made again on every transport fault and on the callee's event; it has "+
"not been answered since %s. Its last fault: %s.", callee, since.UTC().Format(time.RFC3339), fault),
Resolved: "the call is answered", Source: source}
}
@@ -1 +0,0 @@
{"v":1,"key":"machine.g14.silent","kind":"silent-kind","ref":"silent","subject":{"scope":"machine","id":"g14","machine":"g14","also":["ace"]},"severity":"urgent","summary":"g14 is silent","headline":"g14 is silent","explanation":"It said nothing.","resolved":"It speaks.","needs":"look","evidence":[{"at":"2026-11-05T12:00:00Z","said":"no pulse"}],"source":"S1","resolver":"operator","observer":"mesh-delivery-watchman","run":"r1","at":"2026-11-05T12:00:00Z"}
@@ -1 +0,0 @@
{"v":1,"key":"module.nats.g14.build-failed","kind":"build-failed","subject":{"scope":"module","id":"nats.g14"},"severity":"warning","summary":"failed","headline":"","explanation":"","resolved":"","evidence":[{"at":"2026-11-05T12:00:00Z","said":"failed"}],"source":"builder.build-failed","observer":"mesh-delivery-builder","at":"2026-11-05T12:00:00Z"}