Fix 9.7c: a read of a seat holder's state is its own kind, seat:<seat>.<state>
Builds: design 47 G A-128 (A-116) Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
This commit is contained in:
@@ -25,6 +25,9 @@ func SeatFromDefinition(d seatdef.Definition) Seat {
|
||||
Input: seatdef.ResolveRefs(v.Input, d.Defs), Output: seatdef.ResolveRefs(v.Answer, d.Defs),
|
||||
Optional: v.Optional, Replaces: v.Replaces})
|
||||
}
|
||||
for _, st := range d.States {
|
||||
s.States = append(s.States, st.Name)
|
||||
}
|
||||
for _, r := range d.Receives {
|
||||
rv := Receivable{Kind: r.Kind, Comment: r.Comment, Dirs: r.Dirs, Offered: r.Offered}
|
||||
if r.Shape != nil {
|
||||
|
||||
@@ -46,6 +46,9 @@ type Seat struct {
|
||||
// Serves carries each verb in full — name, description, schema — because a role's tools are the
|
||||
// mesh's to define and an agent's to call (novox/hq ADR 0132, design 33 §2).
|
||||
Serves []Verb
|
||||
// States are the names of the state the seat's holder keeps, which a module reads by `seat:<seat>.<state>` (design 47 G
|
||||
// A-116, A-128). Compiled from the definition's states.
|
||||
States []string
|
||||
// Receives is what other modules may contribute to the seat's holder, by kind (novox/hq ADR
|
||||
// 0212): each kind is text in the tool's own grammar, placed by the holder with
|
||||
// ${contribution:<seat>:<kind>}. Compiled, never stored: like the protocol, it is the mesh's
|
||||
|
||||
@@ -78,6 +78,25 @@ func (s StateDeclaration) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(plain(s))
|
||||
}
|
||||
|
||||
// SeatReadPrefix opens a read of the state a seat's holder keeps: `seat:<seat>.<state>` (design 47 G A-116, A-128).
|
||||
const SeatReadPrefix = "seat:"
|
||||
|
||||
// SeatRead splits a read of a seat holder's state, `seat:<seat>.<state>`, into the seat and the local name; ok is false for a
|
||||
// read that is not of this kind (a module's `<module>.<state>`, which ReadState splits), and err says why a `seat:` read is
|
||||
// malformed. The holder is not in it: it is resolved where the read is made (seatholder), so a new holder is read with no
|
||||
// change of the manifest.
|
||||
func SeatRead(read string) (seat, local string, ok bool, err error) {
|
||||
rest, isSeat := strings.CutPrefix(read, SeatReadPrefix)
|
||||
if !isSeat {
|
||||
return "", "", false, nil
|
||||
}
|
||||
at := strings.LastIndex(rest, ".")
|
||||
if at <= 0 || at == len(rest)-1 || !stateName.MatchString(rest[:at]) || !stateName.MatchString(rest[at+1:]) {
|
||||
return "", "", true, fmt.Errorf("%q does not name a seat and its state: a read of a seat holder's state is seat:<seat>.<name>", read)
|
||||
}
|
||||
return rest[:at], rest[at+1:], true, nil
|
||||
}
|
||||
|
||||
// ReadState splits a read into the owning module and the local name, or says why it is not one.
|
||||
func ReadState(read string) (module, local string, err error) {
|
||||
at := strings.LastIndex(read, ".")
|
||||
|
||||
@@ -4,6 +4,8 @@ import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"git.novox.be/novox/mesh-sdk/go/seatdef"
|
||||
)
|
||||
|
||||
// A module declares the state it keeps and the state it reads (novox/hq ADR 0201), a bucket by its
|
||||
@@ -67,3 +69,27 @@ func TestAStateMayHaveKeysThatExpireOneByOne(t *testing.T) {
|
||||
t.Fatalf("read-only given twice: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// A read of a seat holder's state is its own kind, `seat:<seat>.<state>` (design 47 G A-128), and a seat's compiled form
|
||||
// carries the names of the states its definition declares.
|
||||
func TestSeatRead(t *testing.T) {
|
||||
for _, row := range []struct {
|
||||
read, seat, local string
|
||||
ok, bad bool
|
||||
}{
|
||||
{"seat:mesh-provisioner.plans", "mesh-provisioner", "plans", true, false},
|
||||
{"mesh-provisioner.plans", "", "", false, false},
|
||||
{"seat:mesh-provisioner", "", "", true, true},
|
||||
{"seat:.plans", "", "", true, true},
|
||||
{"seat:Mesh.plans", "", "", true, true},
|
||||
} {
|
||||
seat, local, ok, err := SeatRead(row.read)
|
||||
if seat != row.seat || local != row.local || ok != row.ok || (err != nil) != row.bad {
|
||||
t.Errorf("SeatRead(%q) = %q, %q, %v, %v", row.read, seat, local, ok, err)
|
||||
}
|
||||
}
|
||||
s := SeatFromDefinition(seatdef.Definition{Seat: "mesh-provisioner", Scope: "mesh", States: []seatdef.State{{Name: "plans"}, {Name: "provisions"}}})
|
||||
if len(s.States) != 2 || s.States[0] != "plans" || s.States[1] != "provisions" {
|
||||
t.Errorf("the seat's states = %v", s.States)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user