mesh-conditions: observe node-tools' and claude-code's first views and the builder's publishing kinds

Their views findings were written and raised by nobody (ADR 0615 §6). The test finds every catalogue module
writing a views finding in the tree, so a new writer cannot go unobserved; homes for publish-refused,
publish-unanswered, seat-outcome-unread and family-not-heard.

Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
This commit is contained in:
2026-11-04 17:09:58 +01:00
parent 3b01711e1f
commit 1443adc4f0
4 changed files with 64 additions and 7 deletions
@@ -111,6 +111,14 @@ var Homes = map[string]Home{
"floor-silent": {Source: "builder", Observer: builder},
"old-form-held": {Source: "builder", Observer: builder},
"tag-removal-not-done": {Source: "builder", Observer: builder},
// The builder's publishing (design 51): a holder refused the publish, or said nothing past its bound (about the name);
// a holder's outcome the builder cannot read (about the seat).
"publish-refused": {Source: "builder", Observer: builder},
"publish-unanswered": {Source: "builder", Observer: builder},
"seat-outcome-unread": {Source: "builder", Observer: builder},
// A consumer of a delivery part that stopped hearing an event family (ADR 0615 §5), cleared when it binds again: written
// by each of the indexer, the assigner, the builder and the watchman in its own findings, so the kind has no one observer.
"family-not-heard": {Source: "views", Why: "every delivery part whose consumer stopped hearing writes its own"},
// The indexer's own (design 26, ADR 0625): a seat definition that does not parse, generated types out of step with
// their definition, one seat defined by two repositories' trunks, a manifest accepted and not said.
"seat-definition-unparsed": {Source: "indexer", Observer: indexer},
@@ -46,7 +46,9 @@ var Observers = []string{health.WatchmanModule, health.SelfCheckModule, health.H
"mesh-watcher", "minio", "nfs-server", gitea, "mesh-build-go",
// The builder's, the indexer's (asked of its read tool and followed by its views events, ADR 0615 §1) and the other
// readers' of the indexer's and the assigner's state (the registry milestone's join).
builder, indexer, "mesh-delivery-checker", "mesh-delivery-teller", "mesh-delivery-view", enrolment}
builder, indexer, "mesh-delivery-checker", "mesh-delivery-teller", "mesh-delivery-view", enrolment,
// The tool runner's and claude-code's own first views (views.UnansweredFinding in their findings, ADR 0615 §6).
"node-tools", "claude-code"}
// The other states it reads, as `<module>.<name>`.
const (
@@ -3,6 +3,10 @@ package main
import (
"encoding/json"
"fmt"
"io/fs"
"os"
"path/filepath"
"regexp"
"slices"
"sort"
"strings"
@@ -11,6 +15,7 @@ import (
"time"
stdio "git.novox.be/novox/mesh-sdk/go"
"git.novox.be/novox/mesh-sdk/go/delivery"
"git.novox.be/novox/mesh-sdk/go/health"
)
@@ -279,7 +284,8 @@ func TestEveryControllerKindHasItsHome(t *testing.T) {
"data-shrank": selfCheck, "retire-waiting": provisioner, "asks-undelivered": messenger,
"image-missing": artifactStore, "build-failed": builder, "floor-silent": builder, "old-form-held": builder,
"tag-removal-not-done": builder, "seat-definition-unparsed": indexer, "generated-types-out-of-step": indexer,
"seat-defined-twice": indexer, "accepted-unsaid": indexer, "packages-token-refused": gitea} {
"seat-defined-twice": indexer, "accepted-unsaid": indexer, "packages-token-refused": gitea,
"publish-refused": builder, "publish-unanswered": builder, "seat-outcome-unread": builder} {
if h, ok := Homes[kind]; !ok || h.Observer != observer || h.Carried {
t.Errorf("%s's home is %+v", kind, h)
}
@@ -302,21 +308,60 @@ func TestEveryControllerKindHasItsHome(t *testing.T) {
}
}
// The readers' unanswered first view and the owners' views too large to say are every reader's and owner's own.
for _, kind := range []string{"first-view-unanswered", "view-too-large"} {
for _, kind := range []string{"first-view-unanswered", "view-too-large", "family-not-heard"} {
if h := Homes[kind]; h.Observer != "" || h.Carried || h.Controller {
t.Errorf("%s's home is %+v", kind, h)
}
}
// Each module that writes a reader's unanswered first view (ADR 0615 §6) is read.
for _, reader := range []string{watchman, "mesh-delivery-teller", enrolment, builder, "mesh-delivery-checker",
"mesh-delivery-view", indexer, configModule, vaultModule, gitea} {
// Each module that writes a reader's unanswered first view (ADR 0615 §6), or that a delivery part's consumer stopped
// hearing, is read: the delivery parts and the tool runner by name (other repositories), and every catalogue module
// whose code writes a views finding, found in the catalogue's tree, so a new writer cannot go unobserved.
readers := []string{watchman, "mesh-delivery-teller", enrolment, builder, "mesh-delivery-checker", "mesh-delivery-view",
indexer, delivery.AssignerModule, configModule, vaultModule, gitea, "node-tools"}
readers = append(readers, viewFindingWriters(t, "../../..")...)
for _, reader := range readers {
if !slices.Contains(Observers, reader) {
t.Errorf("the reader %s's findings are not read by the keeper", reader)
}
}
// 19 of ADR 0564, the 63 of the table, plan-failed and stalled, mesh-config's four (design 32), the readers' unanswered
// first view, the owners' view too large, the builder's four, the indexer's four and the package seats' token refused.
if len(Homes) != 99 || carried != 37 {
// And the builder's three publishing kinds and the delivery parts' family not heard: 103.
if len(Homes) != 103 || carried != 37 {
t.Errorf("the table holds %d kinds, %d carried", len(Homes), carried)
}
}
// viewFindingWriters are the catalogue modules (under modules) whose non-test Go code writes a views finding into its own
// findings: views.UnansweredFinding, views.TooLargeFinding or views.OwnFindings.
func viewFindingWriters(t *testing.T, modules string) []string {
t.Helper()
writes := regexp.MustCompile(`views\.(UnansweredFinding|TooLargeFinding|OwnFindings)\b`)
var out []string
entries, err := os.ReadDir(modules)
if err != nil {
t.Fatal(err)
}
for _, e := range entries {
if !e.IsDir() || e.Name() == Module {
continue
}
found := false
_ = filepath.WalkDir(filepath.Join(modules, e.Name()), func(path string, d fs.DirEntry, err error) error {
if err != nil || found || d.IsDir() || !strings.HasSuffix(path, ".go") || strings.HasSuffix(path, "_test.go") {
return nil
}
if src, err := os.ReadFile(path); err == nil && writes.Match(src) {
found = true
}
return nil
})
if found {
out = append(out, e.Name())
}
}
if len(out) < 5 {
t.Fatalf("found %d catalogue modules writing views findings in %s: the tree was not read (%v)", len(out), modules, out)
}
return out
}
+2
View File
@@ -32,6 +32,8 @@
"mesh-delivery-teller.findings",
"mesh-delivery-view.findings",
"mesh-enrolment.findings",
"node-tools.findings",
"claude-code.findings",
"mesh-healers.attempts",
"node-engine.have"
],