D1 judge-queue-invokes: an asker's queue and a seat's accepted kind are judged against the seat
The third reader release reads G's invokes `seat:<seat>.accept.<queue>` and `seat:<seat>.<stream>.<kind>` with G's check of them: a queue or kind the seat's definition does not accept is refused, naming it. Builds: design 47 G §601, A-231, A-102, A-343, A-344 Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
This commit is contained in:
@@ -4067,12 +4067,24 @@ func filepathDir(p string) string {
|
||||
}
|
||||
|
||||
// invokeNameValid says a module or process's invoked entry names a tool: <module>.<tool>, a role's
|
||||
// seat:<seat>.<verb>, or * for every tool on the mesh (novox/hq ADR 0152, ADR 0436 §1).
|
||||
// seat:<seat>.<verb> or a kind the seat accepts (seat:<seat>.<kind>, seat:<seat>.<stream>.<kind>, design 47 G A-102),
|
||||
// or * for every tool on the mesh (novox/hq ADR 0152, ADR 0436 §1).
|
||||
func invokeNameValid(t string) bool {
|
||||
if t == "*" {
|
||||
return true
|
||||
}
|
||||
t = strings.TrimPrefix(t, "seat:")
|
||||
if rest, isSeat := strings.CutPrefix(t, "seat:"); isSeat {
|
||||
// A seat's verb, or a kind the seat accepts: `<kind>`, or `<stream>.<kind>` for one that rides a stream (design 47 G
|
||||
// A-102), an asker's queue `accept.<queue>` among them (§601, A-231); seatInvokeProblems judges it against the seat.
|
||||
seat, after, named := strings.Cut(rest, ".")
|
||||
if !named || !name.MatchString(seat) {
|
||||
return false
|
||||
}
|
||||
if stream, kind, onStream := strings.Cut(after, "."); onStream {
|
||||
return toolName.MatchString(stream) && toolName.MatchString(kind)
|
||||
}
|
||||
return toolName.MatchString(after)
|
||||
}
|
||||
first, second, named := strings.Cut(t, ".")
|
||||
return named && name.MatchString(first) && toolName.MatchString(second)
|
||||
}
|
||||
@@ -4586,7 +4598,12 @@ func seatInvokeProblems(shelf catalogue.Shelf, declared map[string]catalogue.Sea
|
||||
problems = append(problems, fmt.Sprintf("%s invokes %s, a verb of the seat %q, "+catalogue.UndeclaredSeat, module, invoke, seat))
|
||||
continue
|
||||
}
|
||||
if !slices.ContainsFunc(verbs, func(v catalogue.Verb) bool { return v.Name == verb }) {
|
||||
// An asker's queue of a build seat, `seat:<seat>.accept.<queue>` (design 47 G §544, §601, A-231), read by mesh-sdk's
|
||||
// one reader: judged against the kinds the seat's definition accepts.
|
||||
if _, queue, isQueue := catalogue.QueueInvoke(invoke); isQueue {
|
||||
verb = queue
|
||||
}
|
||||
if !slices.ContainsFunc(verbs, func(v catalogue.Verb) bool { return v.Name == verb }) && !acceptsKind(seat, verb, declared) {
|
||||
problems = append(problems, fmt.Sprintf("%s invokes %s, and the seat %s serves no verb %q", module, invoke, seat, verb))
|
||||
continue
|
||||
}
|
||||
@@ -4598,6 +4615,15 @@ func seatInvokeProblems(shelf catalogue.Shelf, declared map[string]catalogue.Sea
|
||||
return problems
|
||||
}
|
||||
|
||||
// acceptsKind says the seat accepts the kind an invoke names after its seat (design 47 G A-102): `<kind>`, or
|
||||
// `<stream>.<kind>` for a kind that rides a stream. A module's own seat names its accepts by kind alone.
|
||||
func acceptsKind(seat, kind string, declared map[string]catalogue.SeatDeclaration) bool {
|
||||
if s, isMesh := catalogue.SeatNamed(seat); isMesh {
|
||||
return slices.Contains(s.Accepts, kind) || slices.Contains(s.AcceptedOn, kind)
|
||||
}
|
||||
return slices.Contains(declared[seat].Accepts, kind)
|
||||
}
|
||||
|
||||
// SeatPathProblems is what is wrong with the paths a set of the mesh's own seats names (novox/hq ADR
|
||||
// 0287): only a node seat names one, each absolute and literal; every path has exactly one seat naming it
|
||||
// without stepping back; and a seat steps back only for another node seat naming the same path without
|
||||
|
||||
@@ -5240,6 +5240,11 @@ func caseTwoModulesCannotDeclareTheSameSeat(t *testing.T) {
|
||||
func caseUsingASeatNobodyDeclaresIsRefused(t *testing.T) {
|
||||
unclaimed := telegram()
|
||||
unclaimed.Claims = nil
|
||||
// A mesh seat that accepts a kind riding a stream (design 47 G A-102), beside the seat list's own.
|
||||
was := catalogue.Seats()
|
||||
t.Cleanup(func() { catalogue.UseSeats(was) })
|
||||
catalogue.UseSeats(append(catalogue.Seats(), catalogue.Seat{Name: "mesh-steps", Scope: catalogue.ScopeMesh, Decision: "test",
|
||||
Accepts: []string{"step"}, AcceptedOn: []string{"check.step"}}))
|
||||
for _, row := range []struct {
|
||||
name, want string
|
||||
shop catalogue.Manifest
|
||||
@@ -5268,8 +5273,20 @@ func caseUsingASeatNobodyDeclaresIsRefused(t *testing.T) {
|
||||
{"what the engine reads of a manifest, and its event (ADR 0618 §3, §4)", "",
|
||||
catalogue.Manifest{Module: "shop", Invokes: []string{"seat:node-engine.manifest-reads"},
|
||||
Consumes: []string{"node-engine.manifest-reads-changed"}}, telegram(), false},
|
||||
// An asker names the queue it asks as `seat:<seat>.accept.<queue>`, checked against the kinds the seat's definition
|
||||
// accepts (design 47 G §601, A-231); a kind the seat accepts, alone or on its stream, as `seat:<seat>.<kind>` or
|
||||
// `seat:<seat>.<stream>.<kind>` (A-102).
|
||||
{"a queue a build seat accepts", "", catalogue.Manifest{Module: "shop", Invokes: []string{"seat:node-build-go.accept.check"}}, telegram(), false},
|
||||
{"a queue a build seat does not accept", `the seat node-build-go serves no verb "other"`,
|
||||
catalogue.Manifest{Module: "shop", Invokes: []string{"seat:node-build-go.accept.other"}}, telegram(), false},
|
||||
{"a queue a declared seat accepts", "", catalogue.Manifest{Module: "shop", Invokes: []string{"seat:telegram-sender.accept.send"}}, telegram(), false},
|
||||
{"a kind a seat accepts", "", catalogue.Manifest{Module: "shop", Invokes: []string{"seat:mesh-steps.step"}}, telegram(), false},
|
||||
{"a kind a seat accepts on its stream", "", catalogue.Manifest{Module: "shop", Invokes: []string{"seat:mesh-steps.check.step"}}, telegram(), false},
|
||||
{"a kind on a stream the seat does not take it on", `the seat mesh-steps serves no verb "delivery.step"`,
|
||||
catalogue.Manifest{Module: "shop", Invokes: []string{"seat:mesh-steps.delivery.step"}}, telegram(), false},
|
||||
} {
|
||||
got := CatalogueProblems(catalogue.Shelf{"telegram": row.seat, "shop": row.shop})
|
||||
// The manifest's own invokes rule (at parse) takes the dotted kind as well; the seat's rule then judges it.
|
||||
got := append(invokeProblems(row.shop), CatalogueProblems(catalogue.Shelf{"telegram": row.seat, "shop": row.shop})...)
|
||||
joined := strings.Join(got, "; ")
|
||||
if row.want == "" && joined != "" || row.want != "" && (len(got) != 1 || !strings.Contains(joined, row.want) ||
|
||||
catalogue.IsUndeclaredSeat(got[0]) != row.note) {
|
||||
|
||||
Reference in New Issue
Block a user