Merge pull request 'The condition keeper reads the node-engine's findings; claude-code's seat-list again answers the operator's sessions (issue 1966; group fix/1966-seat-list-unread)' (#650) from fix/1966-seat-list-unread into main

This commit was merged in pull request #650.
This commit is contained in:
2026-11-10 00:44:30 +00:00
5 changed files with 15 additions and 5 deletions
@@ -109,7 +109,9 @@ func TestTheMeshsToolsAreReadFromTheBus(t *testing.T) {
t.Errorf("replacements: %s", got) t.Errorf("replacements: %s", got)
} }
t.Run("the again tool answers the operator and the healers only", func(t *testing.T) { t.Run("the again tool answers the operator and the healers only", func(t *testing.T) {
for caller, refused := range map[string]bool{"person.jochen": false, "shanks.mesh-healers": false, "shanks.mesh-config": true} { // An operator's session through the mesh MCP server is proved as its machine's tool runner (issue 627, issue 1966).
for caller, refused := range map[string]bool{"person.jochen": false, "shanks.node-tools": false, "shanks.mesh-healers": false,
"shanks.mesh-config": true} {
if err := seatlist.Refusal("claude_code_seat_list_again", seatListAgainCallers, caller); (err != nil) != refused { if err := seatlist.Refusal("claude_code_seat_list_again", seatListAgainCallers, caller); (err != nil) != refused {
t.Errorf("%s: refused=%v, err %v", caller, refused, err) t.Errorf("%s: refused=%v, err %v", caller, refused, err)
} }
+4 -2
View File
@@ -667,8 +667,10 @@ func refusals(n int) string {
return fmt.Sprintf(" (after %d refusal(s))", n) return fmt.Sprintf(" (after %d refusal(s))", n)
} }
// seatListAgainCallers may read the seat list again: every operator's session and the healers (ADR 0636 §7). // seatListAgainCallers may read the seat list again: every operator's session and the healers (ADR 0636 §7). A call through
var seatListAgainCallers = []string{stdio.AnyPerson, "mesh-healers"} // the mesh MCP server is proved only as its machine's tool runner (<node>.node-tools, issue 627), so node-tools stands for
// an operator's session until a session is proved (issue 1966).
var seatListAgainCallers = []string{stdio.AnyPerson, "node-tools", "mesh-healers"}
// seatListTools are the seat list reader's two tools: what the list holds and what it waits for, and a read now. The // seatListTools are the seat list reader's two tools: what the list holds and what it waits for, and a read now. The
// reader starts once the runtime serves, after the tools are listed, so each tool finds it when it is called. // reader starts once the runtime serves, after the tools are listed, so each tool finds it when it is called.
@@ -20,6 +20,7 @@ import (
assignerclient "git.novox.be/novox/mesh-contracts/go/clients/meshmoduleassignerclient" assignerclient "git.novox.be/novox/mesh-contracts/go/clients/meshmoduleassignerclient"
mesh "git.novox.be/novox/mesh-contracts/go/seats/meshmoduleassigner" mesh "git.novox.be/novox/mesh-contracts/go/seats/meshmoduleassigner"
stdio "git.novox.be/novox/mesh-sdk/go" stdio "git.novox.be/novox/mesh-sdk/go"
"git.novox.be/novox/mesh-sdk/go/buscompose"
"git.novox.be/novox/mesh-sdk/go/motion" "git.novox.be/novox/mesh-sdk/go/motion"
cc "git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshconditionsclient" cc "git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshconditionsclient"
@@ -65,7 +66,10 @@ var Observers = []string{watchmanModule, selfCheckModule, healersModule, assigne
// readers' of the indexer's and the assigner's state (the registry milestone's join). // 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). // The tool runner's and claude-code's own first views (views.UnansweredFinding in their findings, ADR 0615 §6).
"node-tools", "claude-code"} "node-tools", "claude-code",
// The node-engine's: a node that has read no seat list five minutes after its start, seat-list-unread (ADR 0636 §1;
// issue 1966: written on ace and raised by nobody).
buscompose.EngineModule}
// The other states it reads, as `<module>.<name>`. // The other states it reads, as `<module>.<name>`.
const ( const (
@@ -334,8 +334,9 @@ func TestEveryControllerKindHasItsHome(t *testing.T) {
// Each module that writes a reader's unanswered first view (ADR 0615 §6), or that a delivery part's consumer stopped // 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 // 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. // whose code writes a views finding, found in the catalogue's tree, so a new writer cannot go unobserved.
// And the node-engine, whose node writes seat-list-unread when it has read no seat list (ADR 0636 §1, issue 1966).
readers := []string{watchman, "mesh-delivery-teller", enrolment, builder, "mesh-delivery-checker", "mesh-delivery-view", readers := []string{watchman, "mesh-delivery-teller", enrolment, builder, "mesh-delivery-checker", "mesh-delivery-view",
indexer, assignerModule, configModule, vaultModule, gitea, "node-tools"} indexer, assignerModule, configModule, vaultModule, gitea, "node-tools", "mesh-host"}
readers = append(readers, viewFindingWriters(t, "../../..")...) readers = append(readers, viewFindingWriters(t, "../../..")...)
for _, reader := range readers { for _, reader := range readers {
if !slices.Contains(Observers, reader) { if !slices.Contains(Observers, reader) {
+1
View File
@@ -34,6 +34,7 @@
"mesh-enrolment.findings", "mesh-enrolment.findings",
"node-tools.findings", "node-tools.findings",
"claude-code.findings", "claude-code.findings",
"mesh-host.findings",
"mesh-healers.attempts", "mesh-healers.attempts",
"node-engine.have" "node-engine.have"
], ],