The node-engine seat whole: every verb's answer, its events' bodies, and ADR 0618's manifest-reads and manifest-reads-changed

The seat's area changes in this milestone, so it moves whole into its contracts (ADR 0613 §3): the eleven verbs it serves
get their answers as the engine writes them, asked, done and refused their body, and the seat serves the optional verb
manifest-reads (ADR 0618 §3) and says manifest-reads-changed (§4). Each event is published per node, the node's name its
last token (by-caller), and kept with the seat's events for seven days. compose-candidate's input is a boolean, as the
engine and the checker read it. Fixtures for every event, compose-candidate's input and three answers.

Claude-Session: https://claude.ai/code/session_01JG73KG7AfSdh6FP8VrBqCn
This commit is contained in:
2026-11-04 12:39:56 +01:00
parent f3a9cd17d6
commit 7498d689e2
9 changed files with 3058 additions and 40 deletions
+69
View File
@@ -0,0 +1,69 @@
[
{
"name": "asked on the node's subject",
"of": "event:asked",
"subject": "mesh.seat.node-engine.event.asked.ace",
"given": {
"act": "hand-over",
"subject": "/srv/media",
"caller": "mesh-tools",
"ask": "hand-over-1",
"state": "asked",
"node": "ace"
}
},
{
"name": "done on the node's subject",
"of": "event:done",
"subject": "mesh.seat.node-engine.event.done.ace",
"given": {
"act": "hand-over",
"subject": "/srv/media",
"caller": "mesh-tools",
"ask": "hand-over-1",
"state": "done",
"said": "handed over: owner media, group media, mode 2775",
"node": "ace"
}
},
{
"name": "refused on the node's subject",
"of": "event:refused",
"subject": "mesh.seat.node-engine.event.refused.ace",
"given": {
"act": "access-act",
"subject": "library:music",
"caller": "mesh-tools",
"ask": "access-act-1",
"state": "refused",
"said": "the operator said no",
"node": "ace"
}
},
{
"name": "manifest-reads-changed when the engine started",
"of": "event:manifest-reads-changed",
"subject": "mesh.seat.node-engine.event.manifest-reads-changed.ace",
"given": {
"v": 1,
"node": "ace",
"manifest-reads": [
"form:seat-reference",
"word:series"
],
"at": "2026-11-04T10:00:00Z",
"why": "started"
}
},
{
"name": "manifest-reads-changed when the node returned, from an engine that states none",
"of": "event:manifest-reads-changed",
"subject": "mesh.seat.node-engine.event.manifest-reads-changed.g14",
"given": {
"v": 1,
"node": "g14",
"at": "2026-11-04T10:05:00Z",
"why": "returned"
}
}
]
+76
View File
@@ -0,0 +1,76 @@
[
{
"name": "manifest-reads answers what the engine reads and when it stated it",
"of": "verb:manifest-reads.answer",
"given": {
"v": 1,
"node": "ace",
"manifest-reads": [
"form:seat-reference",
"word:series"
],
"stated-at": "2026-11-04T10:00:00Z"
}
},
{
"name": "manifest-reads of an engine built before it said them is the baseline",
"of": "verb:manifest-reads.answer",
"given": {
"v": 1,
"node": "g14",
"stated-at": "2026-11-04T10:05:00Z"
}
},
{
"name": "compose-candidate asks the candidate and, as a boolean, its composition input",
"of": "verb:compose-candidate.input",
"given": {
"candidate": "mesh-host.0123abcd",
"input": true
}
},
{
"name": "compose-candidate answers per module and the node's own",
"of": "verb:compose-candidate.answer",
"given": {
"v": 1,
"node": "ace",
"candidate": "mesh-host.0123abcd",
"verdict": "composed",
"modules": [
{
"module": "plex",
"fp": "fp-1",
"state": "composed",
"digest": "sha256:aa",
"changed": true
}
],
"own": {
"module": "node",
"state": "composed",
"digest": "sha256:bb"
},
"took": 1200
}
},
{
"name": "acts answers each act kept",
"of": "verb:acts.answer",
"given": {
"node": "ace",
"acts": [
{
"id": "hand-over-1",
"act": "hand-over",
"subject": "/srv/media",
"caller": "mesh-tools",
"at": "2026-11-04T09:00:00Z",
"state": "asked",
"ask": "hand-over-1",
"expires": "2026-11-05T09:00:00Z"
}
]
}
}
]
+872 -11
View File
@@ -2,8 +2,9 @@
"format": 1,
"seat": "node-engine",
"scope": "node",
"grain": "seat-list",
"grain": "whole",
"decision": "novox/hq ADR 0563",
"description": "The node seat every node's engine holds (novox/hq ADR 0563, ADR 0618 §3, §4): its hand acts on the operator's warrant, its read-only judgements, its compositions and what it reads of a manifest. Each verb is answered on this node's subject, mesh.seat.node-engine.tool.<verb>.<node>, and each event is published on mesh.seat.node-engine.event.<event>.<node>, the node's name its last token.",
"held-by-the-engine": true,
"verbs": [
{
@@ -24,6 +25,9 @@
"path"
],
"type": "object"
},
"answer": {
"$ref": "#/defs/Asked"
}
},
{
@@ -49,6 +53,9 @@
"access"
],
"type": "object"
},
"answer": {
"$ref": "#/defs/Asked"
}
},
{
@@ -57,6 +64,9 @@
"input": {
"properties": {},
"type": "object"
},
"answer": {
"$ref": "#/defs/Said"
}
},
{
@@ -70,6 +80,9 @@
}
},
"type": "object"
},
"answer": {
"$ref": "#/defs/Said"
}
},
{
@@ -78,6 +91,21 @@
"input": {
"properties": {},
"type": "object"
},
"answer": {
"type": "object",
"properties": {
"machines": {
"type": "array",
"items": {
"$ref": "#/defs/RootVerdict"
},
"description": "this machine's verdict"
}
},
"required": [
"machines"
]
}
},
{
@@ -95,6 +123,9 @@
}
},
"type": "object"
},
"answer": {
"$ref": "#/defs/Acts"
}
},
{
@@ -113,6 +144,78 @@
}
},
"type": "object"
},
"answer": {
"type": "object",
"properties": {
"node": {
"type": "string",
"description": "the node"
},
"source": {
"type": "string",
"description": "where the key is read: the engine's state packages"
},
"key": {
"type": "object",
"properties": {
"node": {
"type": "string",
"description": "the node"
},
"packages": {
"type": "array",
"items": {
"type": "object",
"properties": {
"package": {
"type": "string",
"description": "the package"
},
"modules": {
"type": "array",
"items": {
"type": "string"
},
"description": "the modules that declare it"
},
"absent": {
"type": "boolean",
"description": "declared absent"
}
},
"required": [
"package",
"modules",
"absent"
]
},
"description": "its packages sorted by name, absent after present"
}
},
"required": [
"node",
"packages"
],
"description": "the node's key as the bus holds it; absent when the engine wrote none"
},
"key_error": {
"type": "string",
"description": "why the key could not be read"
},
"wrote": {
"type": "boolean",
"description": "with write: the key was written again (false: it already held what the engine composed)"
},
"note": {
"type": "string",
"description": "a note, such as that no key is written yet"
}
},
"required": [
"node",
"source"
]
}
},
{
@@ -138,6 +241,255 @@
"module"
],
"type": "object"
},
"answer": {
"type": "object",
"properties": {
"node": {
"type": "string",
"description": "the node"
},
"module": {
"type": "string",
"description": "the module"
},
"want": {
"type": "object",
"properties": {
"fp": {
"type": "string",
"description": "its build's fingerprint"
},
"composed": {
"type": "string",
"description": "the composition's digest it names"
},
"yes": {
"type": "string",
"description": "the digest a person said yes to"
},
"removed": {
"type": "boolean",
"description": "the module is removed"
},
"self": {
"type": "boolean",
"description": "the node composes the module itself (ADR 0547 §2)"
},
"backup": {
"type": "string",
"description": "the operator's answer to a failed backup, again or skip"
},
"words": {
"type": "string",
"description": "its words"
},
"revision": {
"type": "integer",
"description": "the revision of the want's key read last"
}
},
"required": [
"fp",
"revision"
],
"description": "the module's want as the agent holds it; absent when it holds none"
},
"attempt": {
"type": "object",
"properties": {
"fp": {
"type": "string",
"description": "the fingerprint tried"
},
"composed": {
"type": "string",
"description": "the digest tried"
},
"want_revision": {
"type": "integer",
"description": "the want's revision it was tried at"
},
"composition_revision": {
"type": "integer",
"description": "the composition's revision it was tried at"
},
"held": {
"type": "boolean",
"description": "held for a failed backup"
},
"answered_revision": {
"type": "integer",
"description": "the want's revision the hold took"
},
"transient": {
"type": "boolean",
"description": "it failed because the bus did not answer for a moment"
}
},
"required": [
"fp",
"want_revision",
"composition_revision"
],
"description": "the module's last apply that did not end running; absent when none"
},
"started": {
"type": "boolean",
"description": "the agent has looked at the module once since it started"
},
"have": {
"type": "object",
"properties": {
"fp": {
"type": "string",
"description": "fingerprint"
},
"composed": {
"type": "string",
"description": "digest"
},
"phase": {
"type": "string",
"description": "running, failed, held or waiting-yes"
},
"detail": {
"type": "string",
"description": "detail"
},
"judgement": {
"type": "string",
"description": "judgement"
},
"waits": {
"type": "string",
"description": "the digest that waits for a yes"
}
},
"required": [
"phase"
],
"description": "what the module's have key says now; absent when it says nothing"
},
"composition": {
"$ref": "#/defs/Revision"
},
"revisions": {
"type": "array",
"items": {
"$ref": "#/defs/Revision"
},
"description": "the revisions of its key the bucket keeps, oldest first"
},
"runs": {
"type": "object",
"properties": {
"fp": {
"type": "string",
"description": "fingerprint"
},
"composed": {
"type": "string",
"description": "digest"
},
"phase": {
"type": "string",
"description": "phase"
},
"from": {
"type": "string",
"description": "applied, have or kept"
},
"resources": {
"type": "integer",
"description": "how many resources run"
}
},
"required": [
"from",
"resources"
],
"description": "what runs of the module; absent when nothing runs"
},
"judged": {
"type": "object",
"properties": {
"judgement": {
"type": "string",
"description": "the judgement"
},
"words": {
"type": "string",
"description": "its words"
},
"waits_for_yes": {
"type": "boolean",
"description": "the agent would wait for a person's yes before applying it"
}
},
"required": [
"judgement",
"words",
"waits_for_yes"
],
"description": "the move from what runs to the composition read"
},
"diff": {
"type": "array",
"items": {
"type": "object",
"description": "one resource added, removed or changed, as the engine's judge says it"
},
"description": "every resource that differs from what runs, when asked"
},
"own": {
"type": "object",
"properties": {
"provisioner_account": {
"type": "string",
"description": "the account the provisioner's client runs as, as the revision names it"
},
"runs_provisioner_account": {
"type": "string",
"description": "as what runs names it"
},
"adoption": {
"type": "object",
"description": "the revision's adoption; absent for a converged node"
},
"identities": {
"type": "integer",
"description": "identities the revision names"
},
"groups": {
"type": "integer",
"description": "groups"
},
"libraries": {
"type": "integer",
"description": "libraries"
},
"held": {
"type": "object",
"additionalProperties": {
"type": "string"
},
"description": "each module the node's composer held in its last pass, with why"
}
},
"required": [
"provisioner_account"
],
"description": "of the node's own composition, its own fields beside what runs names"
}
},
"required": [
"node",
"module",
"started",
"composition",
"judged"
]
}
},
{
@@ -152,6 +504,55 @@
}
},
"type": "object"
},
"answer": {
"type": "object",
"properties": {
"retried": {
"type": "string",
"description": "the module whose apply was tried again"
},
"pass": {
"type": "object",
"properties": {
"at": {
"type": "string",
"description": "when the pass ended, RFC 3339"
},
"refused": {
"type": "string",
"description": "why the node composed none of its modules"
},
"held": {
"type": "object",
"additionalProperties": {
"type": "string"
},
"description": "each module refused alone, with why"
},
"handed": {
"type": "integer",
"description": "how many compositions the pass handed the agent that differ from before"
},
"again": {
"type": "string",
"description": "when the node composes again on its own, RFC 3339"
},
"earlier": {
"type": "boolean",
"description": "the answer is the last pass, made moments ago"
}
},
"required": [
"at",
"handed"
],
"description": "how the pass went"
}
},
"required": [
"pass"
]
}
},
{
@@ -165,18 +566,72 @@
"type": "string"
},
"input": {
"description": "\"true\": also answer the composition input the candidate was composed from, for the sandbox path",
"enum": [
"true",
"false"
],
"type": "string"
"description": "also answer the composition input the candidate was composed from, for the sandbox path",
"type": "boolean"
}
},
"required": [
"candidate"
],
"type": "object"
},
"answer": {
"type": "object",
"properties": {
"v": {
"type": "integer",
"description": "the layout's version"
},
"node": {
"type": "string",
"description": "the node"
},
"candidate": {
"type": "string",
"description": "the candidate's key"
},
"verdict": {
"type": "string",
"enum": [
"composed",
"refused",
"unready",
"not-judged"
],
"description": "the node's verdict (ADR 0593 §7, §9)"
},
"modules": {
"type": "array",
"items": {
"$ref": "#/defs/Module"
},
"description": "every module placed on the node, sorted by name"
},
"own": {
"$ref": "#/defs/Module"
},
"refused": {
"type": "string",
"description": "why the node could not compose with the candidate at all"
},
"took": {
"type": "integer",
"description": "how long the engine took, in milliseconds"
},
"input": {
"type": "object",
"description": "when asked: the composition input it composed from"
}
},
"required": [
"v",
"node",
"candidate",
"verdict",
"modules",
"own",
"took"
]
}
},
{
@@ -244,17 +699,423 @@
}
}
}
},
{
"name": "manifest-reads",
"optional": true,
"description": "The reader capabilities this machine's engine states (manifest words, forms and seat names it reads, novox/hq ADR 0618 §3) and when it last stated them. An engine built before it said them states none, which a reader takes as the baseline. Read-only. Answered by this machine's engine alone.",
"input": {
"type": "object",
"properties": {}
},
"answer": {
"type": "object",
"properties": {
"v": {
"type": "integer",
"description": "the layout's version"
},
"node": {
"type": "string",
"description": "the node"
},
"manifest-reads": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
},
"description": "the reader capabilities its engine states: the manifest words, forms and seat names it reads; empty for an engine built before it said them, read as the baseline"
},
"stated-at": {
"type": "string",
"description": "when the engine last stated them, RFC 3339"
}
},
"required": [
"v",
"node",
"stated-at"
],
"description": "what this machine's engine reads of a manifest (ADR 0618 §3)"
}
}
],
"events": [
{
"name": "asked"
"name": "asked",
"by-caller": true,
"body": {
"$ref": "#/defs/ActSaid"
}
},
{
"name": "done"
"name": "done",
"by-caller": true,
"body": {
"$ref": "#/defs/ActSaid"
}
},
{
"name": "refused"
"name": "refused",
"by-caller": true,
"body": {
"$ref": "#/defs/ActSaid"
}
},
{
"name": "manifest-reads-changed",
"by-caller": true,
"body": {
"$ref": "#/defs/ManifestReadsChanged"
}
}
]
],
"family": {
"name": "node-engine.events",
"max-age-days": 7
},
"defs": {
"Act": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "the act's id"
},
"act": {
"type": "string",
"description": "the act: hand-over, access-act, judge-directories or setuid-search"
},
"subject": {
"type": "string",
"description": "the path of a hand-over, or the access of an access act"
},
"caller": {
"type": "string",
"description": "the caller as the runtime proved it"
},
"why": {
"type": "string",
"description": "why it was asked, in words"
},
"at": {
"type": "string",
"description": "when it was asked, RFC 3339"
},
"state": {
"type": "string",
"enum": [
"asked",
"done",
"refused",
"answered"
],
"description": "where it stands"
},
"said": {
"type": "string",
"description": "what the engine said of it: its outcome or why it was refused"
},
"ended": {
"type": "string",
"description": "when it ended, RFC 3339"
},
"ask": {
"type": "string",
"description": "the operator's ask of a hand-over or an access act"
},
"sets": {
"type": "string",
"description": "the owner, group and mode it sets, in words"
},
"disk": {
"type": "string",
"description": "what the engine read on disk when it judged"
},
"path": {
"type": "string",
"description": "the directory the act changes"
},
"expires": {
"type": "string",
"description": "when the ask ends unanswered, RFC 3339"
},
"by": {
"type": "string",
"description": "who answered, as the operator's warrant names them"
},
"via": {
"type": "string",
"description": "the channel the warrant came on"
},
"proofs": {
"type": "array",
"items": {
"type": "string"
},
"description": "the warrant's proofs"
},
"auto": {
"type": "boolean",
"description": "the engine asked it itself, on finding a library's root holding data outside its group (ADR 0563 §4)"
}
},
"required": [
"id",
"act",
"caller",
"at",
"state"
],
"description": "one act asked through the seat, as acts reads it (ADR 0563 §9)"
},
"ActSaid": {
"type": "object",
"properties": {
"act": {
"type": "string",
"description": "the act"
},
"subject": {
"type": "string",
"description": "the path or the access"
},
"caller": {
"type": "string",
"description": "the caller as the runtime proved it"
},
"ask": {
"type": "string",
"description": "the operator's ask"
},
"state": {
"type": "string",
"enum": [
"asked",
"done",
"refused"
],
"description": "where the act stands"
},
"said": {
"type": "string",
"description": "what the engine said of it"
},
"node": {
"type": "string",
"description": "the node whose engine says it"
}
},
"required": [
"act",
"caller",
"state",
"node"
],
"description": "what the seat says of an act: the act, the path or access, the caller as the runtime proved it and the ask (ADR 0563 §1)"
},
"Acts": {
"type": "object",
"properties": {
"node": {
"type": "string",
"description": "the node"
},
"acts": {
"type": "array",
"items": {
"$ref": "#/defs/Act"
},
"description": "the acts, newest first"
}
},
"required": [
"node",
"acts"
],
"description": "the acts kept"
},
"Asked": {
"type": "object",
"properties": {
"asked": {
"type": "string",
"description": "the ask's id: acts shows where it stands"
},
"node": {
"type": "string",
"description": "the node"
},
"says": {
"type": "string",
"description": "what happens next, in words"
}
},
"required": [
"asked",
"node",
"says"
],
"description": "the answer of an act the operator is asked"
},
"ManifestReadsChanged": {
"type": "object",
"properties": {
"v": {
"type": "integer",
"description": "the layout's version"
},
"node": {
"type": "string",
"description": "the node"
},
"manifest-reads": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
},
"description": "what its engine states it reads now"
},
"at": {
"type": "string",
"description": "when it says it, RFC 3339"
},
"why": {
"type": "string",
"enum": [
"started",
"returned"
],
"description": "started: the engine started or what it states changed; returned: its node returned after being away"
}
},
"required": [
"v",
"node",
"at",
"why"
],
"description": "what a node-engine says when what it reads changed or its node returned (ADR 0618 §4)"
},
"Module": {
"type": "object",
"properties": {
"module": {
"type": "string",
"description": "the module, node for the node's own composition"
},
"fp": {
"type": "string",
"description": "the fingerprint it was composed at"
},
"state": {
"type": "string",
"enum": [
"composed",
"refused",
"held"
],
"description": "composed (digest set), refused by the candidate, or held without it too (words set)"
},
"digest": {
"type": "string",
"description": "the composition's digest when composed"
},
"changed": {
"type": "boolean",
"description": "the candidate changes it from the one composed without it"
},
"words": {
"type": "string",
"description": "why, for a refused or held one"
}
},
"required": [
"module",
"state"
],
"description": "one module's composition with the candidate"
},
"Revision": {
"type": "object",
"properties": {
"key": {
"type": "string",
"description": "the composition's key"
},
"revision": {
"type": "integer",
"description": "its revision"
},
"digest": {
"type": "string",
"description": "its digest"
},
"resources": {
"type": "integer",
"description": "how many resources it names"
},
"latest": {
"type": "boolean",
"description": "the latest revision"
},
"refused": {
"type": "string",
"description": "why it cannot be read or trusted"
}
},
"required": [
"key"
],
"description": "one revision of a composition key"
},
"RootVerdict": {
"type": "object",
"properties": {
"machine": {
"type": "string",
"description": "the machine"
},
"free": {
"type": "boolean",
"description": "the machine is root-free"
},
"why": {
"type": "string",
"description": "why, in words"
},
"judged": {
"type": "string",
"description": "when the engine judged it, RFC 3339"
}
},
"required": [
"machine",
"free",
"why",
"judged"
],
"description": "the engine's root-free verdict (ADR 0563 §6)"
},
"Said": {
"type": "object",
"properties": {
"node": {
"type": "string",
"description": "the node"
},
"said": {
"type": "string",
"description": "the engine's judgement or search, one line per directory or program"
}
},
"required": [
"node",
"said"
],
"description": "the answer of a read-only judgement"
}
}
}