R-1 rest, R-12, R-13: the capability words are mesh-sdk's, the ledger's fill and removal are answered, the artifact states the words

sent-get is under sent-objects-calls; mesh/ledger.fill answers the history's fill against its cap and mesh/ledger.remove
removes an instance's operations, snapshot, state and index entries, both under ledger-upkeep-calls; the runtime artifact's
`states` is exactly the words the runner states.

Builds: design 47 G §462, §488, §545, §587, §622, §155

Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
This commit is contained in:
2026-11-12 05:02:04 +01:00
parent 64015b5952
commit 5e373af70d
10 changed files with 364 additions and 19 deletions
+51 -9
View File
@@ -3,6 +3,8 @@ package runtime
import (
"encoding/json"
"git.novox.be/novox/mesh-sdk/go/buscalls"
"os"
"slices"
"sort"
"strings"
"testing"
@@ -140,20 +142,60 @@ func TestTheRunnerStatesTheCapabilitiesOfItsCallsInItsPing(t *testing.T) {
t.Fatalf("ping of the instance: %v", err)
}
var ping micro.Ping
if err := json.Unmarshal(msg.Data, &ping); err != nil || ping.Metadata[announce.Capabilities] != "bus-state-calls,ledger-calls,put-sessions,seat-settle-delay" {
if err := json.Unmarshal(msg.Data, &ping); err != nil || ping.Metadata[announce.Capabilities] != "bus-state-calls,ledger-calls,ledger-upkeep-calls,put-sessions,seat-settle-delay,sent-objects-calls" {
t.Errorf("the runner states %q (%v), want its bus-state and ledger calls", ping.Metadata[announce.Capabilities], err)
}
}
// Design 47 G §462: the call that reads a sent object is listed under the bus state capability, and the ledger calls keep theirs.
func TestTheSentObjectCallBelongsToTheBusStateCapability(t *testing.T) {
for c, method := range map[string]string{CapBusStateCalls: buscalls.ObjectsSentGet} {
found := false
for _, m := range callFamilies[c] {
found = found || m == method
// Design 47 G §462, §488, §622: each call is stated under the capability word of its own family, the words mesh-sdk's buscalls
// names: the read of a sent object under sent-objects-calls (no longer under bus-state-calls), the ledger's fill and removal
// under ledger-upkeep-calls, the others where they were.
func TestEachCallIsStatedUnderTheWordOfItsFamily(t *testing.T) {
for method, word := range map[string]string{
buscalls.ObjectsSentGet: buscalls.SentObjectsCalls,
buscalls.LedgerFill: buscalls.LedgerUpkeepCalls,
buscalls.LedgerRemove: buscalls.LedgerUpkeepCalls,
buscalls.LedgerApply: buscalls.LedgerCalls,
buscalls.ObjectsPut: buscalls.BusStateCalls,
} {
var in []string
for c, methods := range callFamilies {
if slices.Contains(methods, method) {
in = append(in, c)
}
}
if !found {
t.Errorf("%s does not list %s", c, method)
if len(in) != 1 || in[0] != word {
t.Errorf("%s is stated under %v, want %s alone", method, in, word)
}
}
}
// Design 47 G §545: the words the tool runner states are exactly its manifest's artifact `states`, so the delivery plan's edge
// of §605 runs to it for each word a module's artifact `calls`.
func TestTheWordsTheRunnerStatesAreItsManifestsStates(t *testing.T) {
raw, err := os.ReadFile("../../module.json")
if err != nil {
t.Fatal(err)
}
var m struct {
Build struct {
Artifacts []struct {
Name string `json:"name"`
States []string `json:"states"`
} `json:"artifacts"`
} `json:"build"`
}
if err := json.Unmarshal(raw, &m); err != nil {
t.Fatal(err)
}
var declared []string
for _, a := range m.Build.Artifacts {
if a.Name == "runtime" {
declared = a.States
}
}
slices.Sort(declared)
if got := CallCapabilities(); !slices.Equal(got, declared) {
t.Errorf("the runner states %v, its manifest's states are %v", got, declared)
}
}
+11 -5
View File
@@ -18,8 +18,12 @@ import (
// (announce.Capabilities) for its machine's node-engine to take into the node's record. A module whose manifest asks for one is
// held off a machine whose runner does not state it.
const (
CapBusStateCalls = "bus-state-calls"
CapLedgerCalls = "ledger-calls"
CapBusStateCalls = buscalls.BusStateCalls
CapLedgerCalls = buscalls.LedgerCalls
// CapLedgerUpkeepCalls is the ledger's fill and removal (§462, §488) and CapSentObjectsCalls the read of a sent object (§488):
// each is stated once the runner answers its family, the words mesh-sdk's buscalls names (§622).
CapLedgerUpkeepCalls = buscalls.LedgerUpkeepCalls
CapSentObjectsCalls = buscalls.SentObjectsCalls
// CapPutSessions is the put and get sessions' word (design 47 G §518, §622), mesh-sdk's.
CapPutSessions = stdio.CapPutSessions
)
@@ -27,10 +31,12 @@ const (
// callFamilies are the methods each capability stands for, the ones BusState and BusStateWatch answer.
var callFamilies = map[string][]string{
CapBusStateCalls: {buscalls.ObjectsPut, buscalls.ObjectsGet, buscalls.ObjectsList, buscalls.ObjectsDelete, buscalls.ObjectsInfo,
buscalls.ObjectsWatch, buscalls.ObjectsSentGet, buscalls.StreamRead, buscalls.StreamFill, buscalls.WorkQueueSize, buscalls.WorkQueueDead},
buscalls.ObjectsWatch, buscalls.StreamRead, buscalls.StreamFill, buscalls.WorkQueueSize, buscalls.WorkQueueDead},
CapLedgerCalls: {buscalls.LedgerApply, buscalls.LedgerGet, buscalls.LedgerHistory, buscalls.LedgerWatch, buscalls.LedgerQuery,
buscalls.LedgerRebuild, buscalls.LedgerReindex, buscalls.LedgerSnapshot, buscalls.LedgerLag},
CapPutSessions: {buscalls.ObjectsPutChunk, buscalls.ObjectsGetChunk},
CapLedgerUpkeepCalls: {buscalls.LedgerFill, buscalls.LedgerRemove},
CapSentObjectsCalls: {buscalls.ObjectsSentGet},
CapPutSessions: {buscalls.ObjectsPutChunk, buscalls.ObjectsGetChunk},
}
// CallCapabilities is every capability of the calls this runner answers, sorted. The delayed settle of a pulled seat
@@ -111,7 +117,7 @@ func (b *moduleBus) BusState(method string, params json.RawMessage) (json.RawMes
answer, err = conn.WorkQueueDead(b.module, r)
}
case buscalls.LedgerApply, buscalls.LedgerGet, buscalls.LedgerHistory, buscalls.LedgerQuery, buscalls.LedgerRebuild,
buscalls.LedgerReindex, buscalls.LedgerSnapshot, buscalls.LedgerLag:
buscalls.LedgerReindex, buscalls.LedgerSnapshot, buscalls.LedgerLag, buscalls.LedgerFill, buscalls.LedgerRemove:
answer, err = b.ledgerCall(method, params)
default:
return nil, fmt.Errorf("the runtime answers no %s", method)
@@ -240,6 +240,35 @@ func TestTheLedgerKeepsItsPromisesOnTheBus(t *testing.T) {
t.Fatalf("queried %+v, %v", q, err)
}
}},
{"fill and removal are answered through the calls and remove an instance from the bus whole", "decision.gone", func(t *testing.T) {
must(t, open(t), "decision/gone", "title", `{"title":"Gone"}`)
must(t, open(t), "decision/gone", "note", `{"says":"two"}`)
must(t, open(t), "decision/stays", "note", `{"says":"kept"}`)
raw, err := m.BusState(buscalls.LedgerFill, json.RawMessage(`{"ledger":"records"}`))
var fill buscalls.Fill
if _ = json.Unmarshal(raw, &fill); err != nil || fill.Count < 3 || fill.Bytes == 0 {
t.Fatalf("the fill answered %s (%v)", raw, err)
}
raw, err = m.BusState(buscalls.LedgerRemove, json.RawMessage(`{"ledger":"records","instance":"decision/gone"}`))
var removed buscalls.LedgerRemoved
if _ = json.Unmarshal(raw, &removed); err != nil || removed.Operations != 2 || removed.Bytes == 0 {
t.Fatalf("the removal answered %s (%v)", raw, err)
}
l := open(t)
if last, _ := l.History.Last("decision.gone"); last != 0 {
t.Fatalf("operations are left, at %d", last)
}
if st, _, _ := l.State.Get("decision.gone"); st != nil {
t.Fatalf("the state is left: %s", st)
}
if last, _ := l.History.Last("decision.stays"); last == 0 {
t.Fatal("another instance lost its operations")
}
if raw, err = m.BusState(buscalls.LedgerRemove, json.RawMessage(`{"ledger":"records","instance":"decision/gone"}`)); err != nil ||
!strings.Contains(string(raw), `"operations":0`) {
t.Fatalf("a removal said twice answered %s (%v)", raw, err)
}
}},
{"a forged author is refused", "decision.forged", func(t *testing.T) {
_, err := m.BusState(buscalls.LedgerApply, json.RawMessage(`{"ledger":"records","instance":"decision/forged","operation":"title","body":{"title":"T","author":"op@shanks"},"call":"forged"}`))
if err == nil || !strings.Contains(err.Error(), "the call forged, which is not a tool call in flight") {
+11
View File
@@ -171,6 +171,17 @@ func (b *moduleBus) ledgerCall(method string, params json.RawMessage) (any, erro
var r buscalls.LedgerRequest
_ = json.Unmarshal(params, &r)
return l.Lag(r)
case buscalls.LedgerFill:
var r buscalls.LedgerRequest
_ = json.Unmarshal(params, &r)
return l.Fill(r)
case buscalls.LedgerRemove:
// Never on an apply: a removal is no operation of the history and has no author (design 47 G §587).
var r buscalls.LedgerRemoveRequest
if err := decode(method, params, &r); err != nil {
return nil, err
}
return l.Remove(r)
}
return nil, fmt.Errorf("the runtime answers no %s", method)
}
+1 -1
View File
@@ -204,7 +204,7 @@ func TestABundleToolNamedAsALedgerRepairIsRefused(t *testing.T) {
// no other name; none answers "the runtime answers no ...".
func TestEveryCallOfAStatedCapabilityIsAnswered(t *testing.T) {
m, _, _ := aLedger(t)
if got := strings.Join(CallCapabilities(), ","); got != "bus-state-calls,ledger-calls,put-sessions,seat-settle-delay" {
if got := strings.Join(CallCapabilities(), ","); got != "bus-state-calls,ledger-calls,ledger-upkeep-calls,put-sessions,seat-settle-delay,sent-objects-calls" {
t.Fatalf("the runner states %s", got)
}
for capability, methods := range callFamilies {