Fixtures captured from the holders' own read tools for the states that had none (conditions, findings, presence, stuck, would, resolved, asks, packages); the packages item requires absent (ADR 0634 §6; issue 1966)

Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
This commit is contained in:
2026-11-05 14:40:27 +01:00
parent f4a69e85f2
commit 551870d8d5
15 changed files with 445 additions and 8 deletions
+12
View File
@@ -25,6 +25,18 @@ func TestFixtures(t *testing.T) {
decode: func(b []byte) (any, error) { var v RetiringHolderEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.stream\\.[a-z0-9-]+\\.event\\.retiring$")},
{name: "retired", subject: "mesh.stream.mesh-config.event.retired", given: "{\"ask\":\"a1\",\"module\":\"messenger\",\"name\":\"old-key\",\"node\":\"ace\"}", wire: "{\"ask\":\"a1\",\"module\":\"messenger\",\"name\":\"old-key\",\"node\":\"ace\"}",
decode: func(b []byte) (any, error) { var v RetiredHolderEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.stream\\.[a-z0-9-]+\\.event\\.retired$")},
{name: "a module's value that falls back to a predefined key (captured)", subject: "", given: "{\"key\":\"font-size\",\"module\":\"dunst\",\"node\":\"g14\",\"predefined\":\"font-size\",\"source\":\"module\",\"value\":13}", wire: "{\"key\":\"font-size\",\"module\":\"dunst\",\"node\":\"g14\",\"predefined\":\"font-size\",\"source\":\"module\",\"value\":13}",
decode: func(b []byte) (any, error) {
var v ResolvedByNodeModuleKeyValue
err := json.Unmarshal(b, &v)
return v, err
}, subjectIs: nil},
{name: "a module's own value (captured)", subject: "", given: "{\"key\":\"width\",\"module\":\"dunst\",\"node\":\"g14\",\"source\":\"module\",\"value\":500}", wire: "{\"key\":\"width\",\"module\":\"dunst\",\"node\":\"g14\",\"source\":\"module\",\"value\":500}",
decode: func(b []byte) (any, error) {
var v ResolvedByNodeModuleKeyValue
err := json.Unmarshal(b, &v)
return v, err
}, subjectIs: nil},
{name: "renames answers the open windows", subject: "", given: "{\"renames\":[{\"at\":\"2026-11-04T12:00:00Z\",\"from\":\"old-key\",\"module\":\"messenger\",\"open\":[\"g14\"],\"to\":\"new-key\"}]}", wire: "{\"renames\":[{\"at\":\"2026-11-04T12:00:00Z\",\"from\":\"old-key\",\"module\":\"messenger\",\"open\":[\"g14\"],\"to\":\"new-key\"}]}",
decode: func(b []byte) (any, error) { var v RenamesAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
}
+3 -3
View File
@@ -978,9 +978,9 @@ type DataByNodeModuleValue struct {
// PackagesByNodeValuePackagesItem is a type of the contract.
type PackagesByNodeValuePackagesItem struct {
Absent bool `json:"absent,omitempty"`
Modules []string `json:"modules,omitempty"`
Package string `json:"package,omitempty"`
Absent bool `json:"absent"`
Modules []string `json:"modules"`
Package string `json:"package"`
}
// PackagesByNodeValue is one value of the state packages under the key <node>.
+2
View File
@@ -37,6 +37,8 @@ func TestFixtures(t *testing.T) {
}, subjectIs: regexp.MustCompile("^mesh\\.seat\\.node-engine\\.event\\.manifest-reads-changed\\.[A-Za-z0-9_-]+$")},
{name: "the finding of a seat list unread, as the engine writes it", subject: "", given: "{\"at\":\"2026-11-05T14:00:00Z\",\"key\":\"machine.ace.seat-list-unread\",\"kind\":\"seat-list-unread\",\"observer\":\"mesh-host\",\"severity\":\"warning\",\"source\":\"node-engine.seat-list\",\"subject\":{\"id\":\"ace\",\"machine\":\"ace\",\"scope\":\"machine\"},\"summary\":\"the seat list has not been read for five minutes\",\"v\":1}", wire: "{\"at\":\"2026-11-05T14:00:00Z\",\"key\":\"machine.ace.seat-list-unread\",\"kind\":\"seat-list-unread\",\"observer\":\"mesh-host\",\"severity\":\"warning\",\"source\":\"node-engine.seat-list\",\"subject\":{\"id\":\"ace\",\"machine\":\"ace\",\"scope\":\"machine\"},\"summary\":\"the seat list has not been read for five minutes\",\"v\":1}",
decode: func(b []byte) (any, error) { var v FindingsByKeyValue; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
{name: "a node's packages, present and absent (captured from ace, shortened)", subject: "", given: "{\"node\":\"ace\",\"packages\":[{\"absent\":false,\"modules\":[\"avahi\"],\"package\":\"avahi\"},{\"absent\":false,\"modules\":[\"mesh-build-go\",\"mesh-build-node\"],\"package\":\"bubblewrap\"},{\"absent\":true,\"modules\":[\"time-sync\"],\"package\":\"ntp\"}]}", wire: "{\"node\":\"ace\",\"packages\":[{\"absent\":false,\"modules\":[\"avahi\"],\"package\":\"avahi\"},{\"absent\":false,\"modules\":[\"mesh-build-go\",\"mesh-build-node\"],\"package\":\"bubblewrap\"},{\"absent\":true,\"modules\":[\"time-sync\"],\"package\":\"ntp\"}]}",
decode: func(b []byte) (any, error) { var v PackagesByNodeValue; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
{name: "manifest-reads answers what the engine reads and when it stated it", subject: "", given: "{\"manifest-reads\":[\"form:seat-reference\",\"word:series\"],\"node\":\"ace\",\"stated-at\":\"2026-11-04T10:00:00Z\",\"v\":1}", wire: "{\"manifest-reads\":[\"form:seat-reference\",\"word:series\"],\"node\":\"ace\",\"stated-at\":\"2026-11-04T10:00:00Z\",\"v\":1}",
decode: func(b []byte) (any, error) { var v ManifestReadsAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
{name: "manifest-reads of an engine built before it said them is the baseline", subject: "", given: "{\"node\":\"g14\",\"stated-at\":\"2026-11-04T10:05:00Z\",\"v\":1}", wire: "{\"node\":\"g14\",\"stated-at\":\"2026-11-04T10:05:00Z\",\"v\":1}",
@@ -0,0 +1,54 @@
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
package meshconditions
import (
"encoding/json"
"reflect"
"regexp"
"testing"
)
// TestFixtures reads every fixture of seats/mesh-conditions/fixtures: each decodes into its type, a field the type does not
// know is dropped (ADR 0608 §6), and it reads back as its wire says; each subject named is the contract's.
func TestFixtures(t *testing.T) {
cases := []struct {
name, subject, given, wire string
decode func([]byte) (any, error)
subjectIs *regexp.Regexp
}{
{name: "a condition raised from a finding, as the keeper holds it (captured; empty fields left out)", subject: "", given: "{\"count\":1,\"evidence\":[{\"at\":\"2026-10-26T20:19:41.474823121Z\",\"said\":\"mesh-build-node on ace uses mesh-build-node.cache as found: used as found: owned by 10005:10005, mode 700, as found; mesh-build-node, mode 0711 was declared and not given it — `ace/node-engine.hand-over` with the directory's path, then your yes on your channel, with its path, hands it to the mesh\"}],\"explanation\":\"Needs you: hand the directory over from the control-node, as the operator; the details name it and the line to type. A directory of mesh-build-node was already on ace, with another owner or mode than mesh-build-node declares.\",\"headline\":\"mesh-build-node waits for a directory on ace\",\"key\":\"module.mesh-build-node.ace.directory-used-as-found\",\"kind\":\"directory-used-as-found\",\"last-observed\":\"2026-10-26T20:19:41.474823121Z\",\"needs\":\"hand the directory over from the control-node, as the operator; the details name it and the line to type.\",\"observations\":1,\"raised\":\"2026-10-31T08:19:57.076843727Z\",\"resolved\":\"mesh-build-node's directory on ace is the mesh's\",\"resolver\":\"self\",\"severity\":\"warning\",\"source\":\"health-report\",\"subject\":{\"id\":\"mesh-build-node.ace\",\"machine\":\"ace\",\"scope\":\"module\"},\"summary\":\"mesh-build-node on ace uses mesh-build-node.cache as found: used as found: owned by 10005:10005, mode 700, as found; mesh-build-node, mode 0711 was declared and not given it — `ace/node-engine.hand-over` with the directory's path, then your yes on your channel, with its path, hands it to the mesh\"}", wire: "{\"count\":1,\"evidence\":[{\"at\":\"2026-10-26T20:19:41.474823121Z\",\"said\":\"mesh-build-node on ace uses mesh-build-node.cache as found: used as found: owned by 10005:10005, mode 700, as found; mesh-build-node, mode 0711 was declared and not given it — `ace/node-engine.hand-over` with the directory's path, then your yes on your channel, with its path, hands it to the mesh\"}],\"explanation\":\"Needs you: hand the directory over from the control-node, as the operator; the details name it and the line to type. A directory of mesh-build-node was already on ace, with another owner or mode than mesh-build-node declares.\",\"headline\":\"mesh-build-node waits for a directory on ace\",\"key\":\"module.mesh-build-node.ace.directory-used-as-found\",\"kind\":\"directory-used-as-found\",\"last-observed\":\"2026-10-26T20:19:41.474823121Z\",\"needs\":\"hand the directory over from the control-node, as the operator; the details name it and the line to type.\",\"observations\":1,\"raised\":\"2026-10-31T08:19:57.076843727Z\",\"resolved\":\"mesh-build-node's directory on ace is the mesh's\",\"resolver\":\"self\",\"severity\":\"warning\",\"source\":\"health-report\",\"subject\":{\"id\":\"mesh-build-node.ace\",\"machine\":\"ace\",\"scope\":\"module\"},\"summary\":\"mesh-build-node on ace uses mesh-build-node.cache as found: used as found: owned by 10005:10005, mode 700, as found; mesh-build-node, mode 0711 was declared and not given it — `ace/node-engine.hand-over` with the directory's path, then your yes on your channel, with its path, hands it to the mesh\"}",
decode: func(b []byte) (any, error) { var v ConditionsByKeyValue; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
{name: "a condition with an empty evidence trail of headline (captured; empty fields left out)", subject: "", given: "{\"count\":1,\"evidence\":[{\"at\":\"2026-10-30T13:03:46.432309782Z\",\"said\":\"The backup of postgres failed on ace\"}],\"explanation\":\"Needs you: answer whether to back up again or go on without a backup. The backup before applying postgres at 978b5db8cb4e on ace failed: node-backup.now could not be asked: not asked: nothing on this machine answers mesh.seat.node-backup.tool.now.ace.\",\"headline\":\"The backup of postgres failed on ace\",\"key\":\"module.ace.postgres.978b5db8cb4ef746ce68d82cc616d1439a53266d335e60f368dc44c4cb25610f.backup\",\"kind\":\"backup\",\"last-observed\":\"2026-10-30T13:03:46.432309782Z\",\"needs\":\"answer whether to back up again or go on without a backup\",\"observations\":1,\"raised\":\"2026-10-31T08:19:57.069818178Z\",\"resolver\":\"self\",\"severity\":\"warning\",\"source\":\"assigner.backup\",\"subject\":{\"id\":\"ace.postgres.978b5db8cb4ef746ce68d82cc616d1439a53266d335e60f368dc44c4cb25610f\",\"machine\":\"ace\",\"scope\":\"module\"},\"summary\":\"The backup of postgres failed on ace\"}", wire: "{\"count\":1,\"evidence\":[{\"at\":\"2026-10-30T13:03:46.432309782Z\",\"said\":\"The backup of postgres failed on ace\"}],\"explanation\":\"Needs you: answer whether to back up again or go on without a backup. The backup before applying postgres at 978b5db8cb4e on ace failed: node-backup.now could not be asked: not asked: nothing on this machine answers mesh.seat.node-backup.tool.now.ace.\",\"headline\":\"The backup of postgres failed on ace\",\"key\":\"module.ace.postgres.978b5db8cb4ef746ce68d82cc616d1439a53266d335e60f368dc44c4cb25610f.backup\",\"kind\":\"backup\",\"last-observed\":\"2026-10-30T13:03:46.432309782Z\",\"needs\":\"answer whether to back up again or go on without a backup\",\"observations\":1,\"raised\":\"2026-10-31T08:19:57.069818178Z\",\"resolver\":\"self\",\"severity\":\"warning\",\"source\":\"assigner.backup\",\"subject\":{\"id\":\"ace.postgres.978b5db8cb4ef746ce68d82cc616d1439a53266d335e60f368dc44c4cb25610f\",\"machine\":\"ace\",\"scope\":\"module\"},\"summary\":\"The backup of postgres failed on ace\"}",
decode: func(b []byte) (any, error) { var v ConditionsByKeyValue; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
{name: "a finding of the bus scope with its zero time (captured from the watchman; empty fields left out)", subject: "", given: "{\"at\":\"0001-01-01T00:00:00Z\",\"evidence\":[{\"at\":\"0001-01-01T00:00:00Z\",\"said\":\"1 held for EVENTS.controller (counted again every 5m0s while any is held, so one delivered again or dropped ends this within it)\"}],\"key\":\"bus.EVENTS.controller.max-deliveries\",\"kind\":\"max-deliveries\",\"needs\":\"deliver them again or drop them, from the mesh MCP server.\",\"observer\":\"mesh-delivery-watchman\",\"severity\":\"warning\",\"source\":\"S9\",\"subject\":{\"id\":\"EVENTS.controller\",\"scope\":\"bus\"},\"summary\":\"the controller's consumer on EVENTS gave up on a message; it is kept in DEAD_LETTERS until delivered again or dropped, with why\",\"v\":1}", wire: "{\"at\":\"0001-01-01T00:00:00Z\",\"evidence\":[{\"at\":\"0001-01-01T00:00:00Z\",\"said\":\"1 held for EVENTS.controller (counted again every 5m0s while any is held, so one delivered again or dropped ends this within it)\"}],\"key\":\"bus.EVENTS.controller.max-deliveries\",\"kind\":\"max-deliveries\",\"needs\":\"deliver them again or drop them, from the mesh MCP server.\",\"observer\":\"mesh-delivery-watchman\",\"severity\":\"warning\",\"source\":\"S9\",\"subject\":{\"id\":\"EVENTS.controller\",\"scope\":\"bus\"},\"summary\":\"the controller's consumer on EVENTS gave up on a message; it is kept in DEAD_LETTERS until delivered again or dropped, with why\",\"v\":1}",
decode: func(b []byte) (any, error) { var v FindingsByKeyValue; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
{name: "a finding of the module scope with its machine (captured from the watchman; empty fields left out)", subject: "", given: "{\"at\":\"2026-10-26T20:19:41.474823121Z\",\"evidence\":[{\"at\":\"2026-10-26T20:19:41.474823121Z\",\"said\":\"mesh-build-node on ace uses mesh-build-node.cache as found: owned by 10005:10005, mode 700, as found\"}],\"explanation\":\"Needs you: hand the directory over from the control-node, as the operator.\",\"headline\":\"mesh-build-node waits for a directory on ace\",\"key\":\"module.mesh-build-node.ace.directory-used-as-found\",\"kind\":\"directory-used-as-found\",\"needs\":\"hand the directory over from the control-node, as the operator; the details name it and the line to type.\",\"observer\":\"mesh-delivery-watchman\",\"resolved\":\"mesh-build-node's directory on ace is the mesh's\",\"severity\":\"warning\",\"source\":\"health-report\",\"subject\":{\"id\":\"mesh-build-node.ace\",\"machine\":\"ace\",\"scope\":\"module\"},\"summary\":\"mesh-build-node on ace uses mesh-build-node.cache as found\",\"v\":1}", wire: "{\"at\":\"2026-10-26T20:19:41.474823121Z\",\"evidence\":[{\"at\":\"2026-10-26T20:19:41.474823121Z\",\"said\":\"mesh-build-node on ace uses mesh-build-node.cache as found: owned by 10005:10005, mode 700, as found\"}],\"explanation\":\"Needs you: hand the directory over from the control-node, as the operator.\",\"headline\":\"mesh-build-node waits for a directory on ace\",\"key\":\"module.mesh-build-node.ace.directory-used-as-found\",\"kind\":\"directory-used-as-found\",\"needs\":\"hand the directory over from the control-node, as the operator; the details name it and the line to type.\",\"observer\":\"mesh-delivery-watchman\",\"resolved\":\"mesh-build-node's directory on ace is the mesh's\",\"severity\":\"warning\",\"source\":\"health-report\",\"subject\":{\"id\":\"mesh-build-node.ace\",\"machine\":\"ace\",\"scope\":\"module\"},\"summary\":\"mesh-build-node on ace uses mesh-build-node.cache as found\",\"v\":1}",
decode: func(b []byte) (any, error) { var v FindingsByKeyValue; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
}
for _, c := range cases {
v, err := c.decode([]byte(c.given))
if err != nil {
t.Errorf("%s: does not decode: %v", c.name, err)
continue
}
back, err := json.Marshal(v)
if err != nil {
t.Errorf("%s: does not encode: %v", c.name, err)
continue
}
var got, want any
if err := json.Unmarshal(back, &got); err != nil {
t.Fatal(err)
}
if err := json.Unmarshal([]byte(c.wire), &want); err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(got, want) {
t.Errorf("%s: reads back as %s, want %s", c.name, back, c.wire)
}
if c.subjectIs != nil && !c.subjectIs.MatchString(c.subject) {
t.Errorf("%s: subject %q is not the contract's %s", c.name, c.subject, c.subjectIs)
}
}
}
@@ -0,0 +1,48 @@
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
package meshhealers
import (
"encoding/json"
"reflect"
"regexp"
"testing"
)
// TestFixtures reads every fixture of seats/mesh-healers/fixtures: each decodes into its type, a field the type does not
// know is dropped (ADR 0608 §6), and it reads back as its wire says; each subject named is the contract's.
func TestFixtures(t *testing.T) {
cases := []struct {
name, subject, given, wire string
decode func([]byte) (any, error)
subjectIs *regexp.Regexp
}{
{name: "an act a healer would have made, kept from the controller's time (captured)", subject: "", given: "{\"act\":\"assert the module's buckets, logs and streams again through the grants part (grants_assert)\",\"at\":\"2026-11-02T08:15:56.49507336Z\",\"condition\":\"bus.EVENTS.4fs9xzyDY7CD2Cf1wVFYDK_1.consumer-lost\",\"healer\":\"H3\",\"kind\":\"consumer-lost\",\"why\":\"the controller's lease names a controller (or none is written, so one may take it): every act is written as would\"}", wire: "{\"act\":\"assert the module's buckets, logs and streams again through the grants part (grants_assert)\",\"at\":\"2026-11-02T08:15:56.49507336Z\",\"condition\":\"bus.EVENTS.4fs9xzyDY7CD2Cf1wVFYDK_1.consumer-lost\",\"healer\":\"H3\",\"kind\":\"consumer-lost\",\"why\":\"the controller's lease names a controller (or none is written, so one may take it): every act is written as would\"}",
decode: func(b []byte) (any, error) { var v WouldByWouldValue; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
}
for _, c := range cases {
v, err := c.decode([]byte(c.given))
if err != nil {
t.Errorf("%s: does not decode: %v", c.name, err)
continue
}
back, err := json.Marshal(v)
if err != nil {
t.Errorf("%s: does not encode: %v", c.name, err)
continue
}
var got, want any
if err := json.Unmarshal(back, &got); err != nil {
t.Fatal(err)
}
if err := json.Unmarshal([]byte(c.wire), &want); err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(got, want) {
t.Errorf("%s: reads back as %s, want %s", c.name, back, c.wire)
}
if c.subjectIs != nil && !c.subjectIs.MatchString(c.subject) {
t.Errorf("%s: subject %q is not the contract's %s", c.name, c.subject, c.subjectIs)
}
}
}
@@ -0,0 +1,56 @@
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
package meshwatchdogs
import (
"encoding/json"
"reflect"
"regexp"
"testing"
)
// TestFixtures reads every fixture of seats/mesh-watchdogs/fixtures: each decodes into its type, a field the type does not
// know is dropped (ADR 0608 §6), and it reads back as its wire says; each subject named is the contract's.
func TestFixtures(t *testing.T) {
cases := []struct {
name, subject, given, wire string
decode func([]byte) (any, error)
subjectIs *regexp.Regexp
}{
{name: "a node's agent online (captured)", subject: "", given: "{\"online\":true,\"v\":1}", wire: "{\"online\":true,\"v\":1}",
decode: func(b []byte) (any, error) { var v PresenceByNodeValue; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
{name: "a delivery part's instance online (captured)", subject: "", given: "{\"online\":true,\"v\":1}", wire: "{\"online\":true,\"v\":1}",
decode: func(b []byte) (any, error) {
var v PresenceByPartPartInstanceValue
err := json.Unmarshal(b, &v)
return v, err
}, subjectIs: nil},
{name: "a thing that has not moved since a time, with what it waited for (captured)", subject: "", given: "{\"bucket\":\"mesh-delivery-watchman_presence\",\"key\":\"part.mesh-delivery-builder.novox\",\"since\":\"2026-10-25T11:52:58.051397201+01:00\",\"v\":1,\"waited\":\"mesh-delivery-builder on novox to come back online\"}", wire: "{\"bucket\":\"mesh-delivery-watchman_presence\",\"key\":\"part.mesh-delivery-builder.novox\",\"since\":\"2026-10-25T11:52:58.051397201+01:00\",\"v\":1,\"waited\":\"mesh-delivery-builder on novox to come back online\"}",
decode: func(b []byte) (any, error) { var v StuckByBucketKeyValue; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
}
for _, c := range cases {
v, err := c.decode([]byte(c.given))
if err != nil {
t.Errorf("%s: does not decode: %v", c.name, err)
continue
}
back, err := json.Marshal(v)
if err != nil {
t.Errorf("%s: does not encode: %v", c.name, err)
continue
}
var got, want any
if err := json.Unmarshal(back, &got); err != nil {
t.Fatal(err)
}
if err := json.Unmarshal([]byte(c.wire), &want); err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(got, want) {
t.Errorf("%s: reads back as %s, want %s", c.name, back, c.wire)
}
if c.subjectIs != nil && !c.subjectIs.MatchString(c.subject) {
t.Errorf("%s: subject %q is not the contract's %s", c.name, c.subject, c.subjectIs)
}
}
}
@@ -0,0 +1,117 @@
[
{
"name": "a condition raised from a finding, as the keeper holds it (captured; empty fields left out)",
"of": "state:conditions/<key>",
"given": {
"count": 1,
"evidence": [
{
"at": "2026-10-26T20:19:41.474823121Z",
"said": "mesh-build-node on ace uses mesh-build-node.cache as found: used as found: owned by 10005:10005, mode 700, as found; mesh-build-node, mode 0711 was declared and not given it \u2014 `ace/node-engine.hand-over` with the directory's path, then your yes on your channel, with its path, hands it to the mesh"
}
],
"explanation": "Needs you: hand the directory over from the control-node, as the operator; the details name it and the line to type. A directory of mesh-build-node was already on ace, with another owner or mode than mesh-build-node declares.",
"headline": "mesh-build-node waits for a directory on ace",
"key": "module.mesh-build-node.ace.directory-used-as-found",
"kind": "directory-used-as-found",
"last-observed": "2026-10-26T20:19:41.474823121Z",
"needs": "hand the directory over from the control-node, as the operator; the details name it and the line to type.",
"observations": 1,
"raised": "2026-10-31T08:19:57.076843727Z",
"resolved": "mesh-build-node's directory on ace is the mesh's",
"resolver": "self",
"severity": "warning",
"source": "health-report",
"subject": {
"id": "mesh-build-node.ace",
"machine": "ace",
"scope": "module"
},
"summary": "mesh-build-node on ace uses mesh-build-node.cache as found: used as found: owned by 10005:10005, mode 700, as found; mesh-build-node, mode 0711 was declared and not given it \u2014 `ace/node-engine.hand-over` with the directory's path, then your yes on your channel, with its path, hands it to the mesh"
}
},
{
"name": "a condition with an empty evidence trail of headline (captured; empty fields left out)",
"of": "state:conditions/<key>",
"given": {
"count": 1,
"evidence": [
{
"at": "2026-10-30T13:03:46.432309782Z",
"said": "The backup of postgres failed on ace"
}
],
"explanation": "Needs you: answer whether to back up again or go on without a backup. The backup before applying postgres at 978b5db8cb4e on ace failed: node-backup.now could not be asked: not asked: nothing on this machine answers mesh.seat.node-backup.tool.now.ace.",
"headline": "The backup of postgres failed on ace",
"key": "module.ace.postgres.978b5db8cb4ef746ce68d82cc616d1439a53266d335e60f368dc44c4cb25610f.backup",
"kind": "backup",
"last-observed": "2026-10-30T13:03:46.432309782Z",
"needs": "answer whether to back up again or go on without a backup",
"observations": 1,
"raised": "2026-10-31T08:19:57.069818178Z",
"resolver": "self",
"severity": "warning",
"source": "assigner.backup",
"subject": {
"id": "ace.postgres.978b5db8cb4ef746ce68d82cc616d1439a53266d335e60f368dc44c4cb25610f",
"machine": "ace",
"scope": "module"
},
"summary": "The backup of postgres failed on ace"
}
},
{
"name": "a finding of the bus scope with its zero time (captured from the watchman; empty fields left out)",
"of": "state:findings/<key>",
"given": {
"v": 1,
"key": "bus.EVENTS.controller.max-deliveries",
"kind": "max-deliveries",
"subject": {
"id": "EVENTS.controller",
"scope": "bus"
},
"severity": "warning",
"summary": "the controller's consumer on EVENTS gave up on a message; it is kept in DEAD_LETTERS until delivered again or dropped, with why",
"needs": "deliver them again or drop them, from the mesh MCP server.",
"observer": "mesh-delivery-watchman",
"source": "S9",
"evidence": [
{
"at": "0001-01-01T00:00:00Z",
"said": "1 held for EVENTS.controller (counted again every 5m0s while any is held, so one delivered again or dropped ends this within it)"
}
],
"at": "0001-01-01T00:00:00Z"
}
},
{
"name": "a finding of the module scope with its machine (captured from the watchman; empty fields left out)",
"of": "state:findings/<key>",
"given": {
"v": 1,
"key": "module.mesh-build-node.ace.directory-used-as-found",
"kind": "directory-used-as-found",
"subject": {
"id": "mesh-build-node.ace",
"machine": "ace",
"scope": "module"
},
"severity": "warning",
"summary": "mesh-build-node on ace uses mesh-build-node.cache as found",
"explanation": "Needs you: hand the directory over from the control-node, as the operator.",
"headline": "mesh-build-node waits for a directory on ace",
"needs": "hand the directory over from the control-node, as the operator; the details name it and the line to type.",
"resolved": "mesh-build-node's directory on ace is the mesh's",
"observer": "mesh-delivery-watchman",
"source": "health-report",
"evidence": [
{
"at": "2026-10-26T20:19:41.474823121Z",
"said": "mesh-build-node on ace uses mesh-build-node.cache as found: owned by 10005:10005, mode 700, as found"
}
],
"at": "2026-10-26T20:19:41.474823121Z"
}
}
]
@@ -0,0 +1,14 @@
[
{
"name": "an act a healer would have made, kept from the controller's time (captured)",
"of": "state:would/<would>",
"given": {
"act": "assert the module's buckets, logs and streams again through the grants part (grants_assert)",
"at": "2026-11-02T08:15:56.49507336Z",
"condition": "bus.EVENTS.4fs9xzyDY7CD2Cf1wVFYDK_1.consumer-lost",
"healer": "H3",
"kind": "consumer-lost",
"why": "the controller's lease names a controller (or none is written, so one may take it): every act is written as would"
}
}
]
@@ -0,0 +1,29 @@
[
{
"name": "a node's agent online (captured)",
"of": "state:presence/<node>",
"given": {
"online": true,
"v": 1
}
},
{
"name": "a delivery part's instance online (captured)",
"of": "state:presence/part.<part>.<instance>",
"given": {
"online": true,
"v": 1
}
},
{
"name": "a thing that has not moved since a time, with what it waited for (captured)",
"of": "state:stuck/<bucket>.<key>",
"given": {
"bucket": "mesh-delivery-watchman_presence",
"key": "part.mesh-delivery-builder.novox",
"since": "2026-10-25T11:52:58.051397201+01:00",
"v": 1,
"waited": "mesh-delivery-builder on novox to come back online"
}
}
]
@@ -31,6 +31,10 @@ func TestFixtures(t *testing.T) {
decode: func(b []byte) (any, error) { var v CancelAccept; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.operator-channel\\.accept\\.cancel\\.[A-Za-z0-9_-]+$")},
{name: "a condition by its publisher", subject: "mesh.seat.operator-channel.accept.condition.mesh-watcher", given: "{\"key\":\"backup.ace.failed\",\"severity\":\"warning\",\"state\":\"raised\",\"subject\":{\"id\":\"ace\",\"scope\":\"node\"},\"v\":1}", wire: "{\"key\":\"backup.ace.failed\",\"severity\":\"warning\",\"state\":\"raised\",\"subject\":{\"id\":\"ace\",\"scope\":\"node\"},\"v\":1}",
decode: func(b []byte) (any, error) { var v ConditionAccept; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.operator-channel\\.accept\\.condition\\.[A-Za-z0-9_-]+$")},
{name: "an ask chosen on a channel, as the router's tool states it (captured)", subject: "", given: "{\"answer\":\"the operator, via telegram (user id verified), chose Approve\",\"asker\":\"mesh-knowledge\",\"asker_told\":true,\"expires\":\"2026-11-06T12:17:43Z\",\"headline\":\"Parts wait for the seat list before acting\",\"key\":\"mesh-knowledge.kb-decision-636-1bcf1a2c\",\"offered_on\":[\"telegram\"],\"opened\":\"2026-11-05T12:27:44Z\",\"state\":\"chosen\"}", wire: "{\"answer\":\"the operator, via telegram (user id verified), chose Approve\",\"asker\":\"mesh-knowledge\",\"asker_told\":true,\"expires\":\"2026-11-06T12:17:43Z\",\"headline\":\"Parts wait for the seat list before acting\",\"key\":\"mesh-knowledge.kb-decision-636-1bcf1a2c\",\"offered_on\":[\"telegram\"],\"opened\":\"2026-11-05T12:27:44Z\",\"state\":\"chosen\"}",
decode: func(b []byte) (any, error) { var v AsksByAskerIDValue; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
{name: "an ask its asker took back (captured)", subject: "", given: "{\"answer\":\"cancelled: its asker took it back\",\"asker\":\"mesh-delivery-teller\",\"asker_told\":true,\"expires\":\"2026-11-06T10:04:01Z\",\"headline\":\"Check failed - merge into main\",\"key\":\"mesh-delivery-teller.merge-feat_registry_milestone-3a038b9f8b4d-4-4da6ee3cd9d5\",\"offered_on\":[\"telegram\"],\"opened\":\"2026-11-05T10:14:04Z\",\"state\":\"cancelled\"}", wire: "{\"answer\":\"cancelled: its asker took it back\",\"asker\":\"mesh-delivery-teller\",\"asker_told\":true,\"expires\":\"2026-11-06T10:04:01Z\",\"headline\":\"Check failed - merge into main\",\"key\":\"mesh-delivery-teller.merge-feat_registry_milestone-3a038b9f8b4d-4-4da6ee3cd9d5\",\"offered_on\":[\"telegram\"],\"opened\":\"2026-11-05T10:14:04Z\",\"state\":\"cancelled\"}",
decode: func(b []byte) (any, error) { var v AsksByAskerIDValue; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
}
for _, c := range cases {
v, err := c.decode([]byte(c.given))
@@ -0,0 +1,36 @@
[
{
"name": "an ask chosen on a channel, as the router's tool states it (captured)",
"of": "state:asks/<asker>.<id>",
"given": {
"answer": "the operator, via telegram (user id verified), chose Approve",
"asker": "mesh-knowledge",
"asker_told": true,
"expires": "2026-11-06T12:17:43Z",
"headline": "Parts wait for the seat list before acting",
"key": "mesh-knowledge.kb-decision-636-1bcf1a2c",
"offered_on": [
"telegram"
],
"opened": "2026-11-05T12:27:44Z",
"state": "chosen"
}
},
{
"name": "an ask its asker took back (captured)",
"of": "state:asks/<asker>.<id>",
"given": {
"answer": "cancelled: its asker took it back",
"asker": "mesh-delivery-teller",
"asker_told": true,
"expires": "2026-11-06T10:04:01Z",
"headline": "Check failed - merge into main",
"key": "mesh-delivery-teller.merge-feat_registry_milestone-3a038b9f8b4d-4-4da6ee3cd9d5",
"offered_on": [
"telegram"
],
"opened": "2026-11-05T10:14:04Z",
"state": "cancelled"
}
}
]
+25
View File
@@ -0,0 +1,25 @@
[
{
"name": "a module's value that falls back to a predefined key (captured)",
"of": "state:resolved/<node>.<module>.<key>",
"given": {
"node": "g14",
"module": "dunst",
"key": "font-size",
"predefined": "font-size",
"source": "module",
"value": 13
}
},
{
"name": "a module's own value (captured)",
"of": "state:resolved/<node>.<module>.<key>",
"given": {
"node": "g14",
"module": "dunst",
"key": "width",
"source": "module",
"value": 500
}
}
]
+36 -1
View File
@@ -6,12 +6,47 @@
"v": 1,
"key": "machine.ace.seat-list-unread",
"kind": "seat-list-unread",
"subject": {"scope": "machine", "id": "ace", "machine": "ace"},
"subject": {
"scope": "machine",
"id": "ace",
"machine": "ace"
},
"severity": "warning",
"summary": "the seat list has not been read for five minutes",
"source": "node-engine.seat-list",
"observer": "mesh-host",
"at": "2026-11-05T14:00:00Z"
}
},
{
"name": "a node's packages, present and absent (captured from ace, shortened)",
"of": "state:packages/<node>",
"given": {
"node": "ace",
"packages": [
{
"absent": false,
"modules": [
"avahi"
],
"package": "avahi"
},
{
"absent": false,
"modules": [
"mesh-build-go",
"mesh-build-node"
],
"package": "bubblewrap"
},
{
"absent": true,
"modules": [
"time-sync"
],
"package": "ntp"
}
]
}
}
]
+6 -1
View File
@@ -1012,7 +1012,12 @@
"absent": {
"type": "boolean"
}
}
},
"required": [
"package",
"modules",
"absent"
]
}
}
},
+3 -3
View File
@@ -782,9 +782,9 @@ export interface DataByNodeModuleValue {
}
export interface PackagesByNodeValuePackagesItem {
"absent"?: boolean;
"modules"?: string[];
"package"?: string;
"absent": boolean;
"modules": string[];
"package": string;
}
/** is one value of the state packages under the key <node>. */