Keep each placed module's data items in the engine's state data, so disk-load measures without composing (ADR 0577)

After a pass that handed a new composition, the node's composer works out its modules' data
items from the inputs it composed from and writes each module's key <node>.<module> of
mesh-host_data only when it differs, deleting the keys of modules that left. Pins mesh-sdk
feat/data-items for the contract and the engine's grant. Two tool-answer tests are merged so
the unit count stays where it was.

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
This commit is contained in:
2026-11-01 00:09:25 +01:00
parent 6c1f7cc7f5
commit e0261cdfc1
10 changed files with 485 additions and 17 deletions
+12
View File
@@ -87,6 +87,9 @@ type Env struct {
// 0550 §2): asked only when a module placed here asks for a certificate and the record holds none from an authority
// the node trusts. Nil asks nothing, and such a module stands in, as before.
Certify func(ctx context.Context) error
// Data is this node's keys of the engine's state data (novox/hq ADR 0577 clause 1), where each placed module's data
// items are kept after a pass that composed something new. Nil keeps none.
Data DataStore
}
// VaultSecretChanged is the vault's event that a secret changed: a name and its generation, never a value.
@@ -146,6 +149,12 @@ type Composer struct {
last Pass
// watching says the composer's loop runs (Watch), so an ask of a pass can be answered.
watching atomic.Bool
// dataDue says a pass composed something new (or is the run's first), so the data items are kept again
// (publishData); dataSaid is the last line said of them. Under mu. dataKept is what this node's keys of the state
// data hold, read once per run, nil before; the loop's alone.
dataDue bool
dataSaid string
dataKept map[string][]byte
}
// Pass is how one pass went, as the node-engine's verb compose answers it.
@@ -432,6 +441,7 @@ func (c *Composer) Watch(ctx context.Context, _ string) (<-chan agent.Update, er
return
}
}
c.publishData(ctx)
if c.owed.Load() {
wait, _ := c.waitNow()
c.env.Say(fmt.Sprintf("the node composes again in %s: a read on the bus did not answer", wait))
@@ -894,6 +904,8 @@ func (c *Composer) compose(ctx context.Context) []agent.Update {
}
}
pass.Handed = len(out)
// The data items are kept again after a pass that handed something new, and after the run's first (ADR 0577 clause 1).
c.dataDue = c.dataDue || len(out) > 0 || c.dataKept == nil
return out
}