EE-D4: the validator has no rule about the waits list
The manifest no longer carries what a session waits on (mesh-sdk EE-S2), so the rule judging it and its token form go; a manifest still carrying waits is a field the validator does not know, refused by Shelf and set aside by ShelfWaiting, and the tool runner's manifest without it is accepted. Builds: design 34 every-event §10 Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
This commit is contained in:
@@ -2938,7 +2938,6 @@ func parseManifest(raw []byte, predefined catalogue.PredefinedList) (catalogue.M
|
||||
}
|
||||
}
|
||||
problems = append(problems, invokeProblems(m)...)
|
||||
problems = append(problems, waitProblems(m)...)
|
||||
problems = append(problems, replacesProblems(m)...)
|
||||
problems = append(problems, UnitSettingProblems(m)...)
|
||||
problems = append(problems, OwnerSettingProblems(m)...)
|
||||
@@ -3390,43 +3389,6 @@ func replacesProblems(m catalogue.Manifest) []string {
|
||||
return problems
|
||||
}
|
||||
|
||||
// waitProblems judges the event families a module says a session may wait on (novox/hq ADR 0367 §2, §6):
|
||||
// the tool runner's alone, each named whole — emitter and event, with no wildcard — and each once. Refused
|
||||
// here, in the manifest's words, rather than at the composition of the bus's users.
|
||||
func waitProblems(m catalogue.Manifest) []string {
|
||||
if len(m.Waits) == 0 {
|
||||
return nil
|
||||
}
|
||||
if !catalogue.IsToolRunner(m) {
|
||||
return []string{fmt.Sprintf("%s says what a session waits on; only the tool runner's module (it says "+
|
||||
"\"tool-runner\": true) declares waits (novox/hq ADR 0367 §2)", m.Module)}
|
||||
}
|
||||
var problems []string
|
||||
seen := map[string]bool{}
|
||||
for _, w := range m.Waits {
|
||||
if strings.ContainsAny(w, "*>") {
|
||||
problems = append(problems, fmt.Sprintf("%s waits on %q: a family is named one by one, never a "+
|
||||
"wildcard (novox/hq ADR 0367 §2)", m.Module, w))
|
||||
continue
|
||||
}
|
||||
tokens := strings.Split(w, ".")
|
||||
whole := len(tokens) >= 2 && name.MatchString(tokens[0])
|
||||
for _, t := range tokens[1:] {
|
||||
whole = whole && waitToken.MatchString(t)
|
||||
}
|
||||
if !whole {
|
||||
problems = append(problems, fmt.Sprintf("%s waits on %q, which does not name an emitter and an "+
|
||||
"event: a family is <emitter>.<event>, as consumes names one", m.Module, w))
|
||||
continue
|
||||
}
|
||||
if seen[w] {
|
||||
problems = append(problems, fmt.Sprintf("%s waits on %q twice", m.Module, w))
|
||||
}
|
||||
seen[w] = true
|
||||
}
|
||||
return problems
|
||||
}
|
||||
|
||||
// whileStoppedProblems judges one container's maintenance window against its own definition
|
||||
// (novox/hq ADR 0189).
|
||||
//
|
||||
@@ -3646,8 +3608,6 @@ var renamed = map[string]string{
|
||||
|
||||
var toolName = regexp.MustCompile(`^[a-z0-9][a-z0-9_-]*$`)
|
||||
|
||||
var waitToken = regexp.MustCompile(`^[a-z0-9][a-z0-9_-]*$`)
|
||||
|
||||
var engineGeneric = map[string]string{
|
||||
"database": "postgres-database, mssql-database, mariadb-database",
|
||||
"db": "postgres-database, mssql-database, mariadb-database",
|
||||
|
||||
@@ -3156,29 +3156,20 @@ func caseAVerbWithAnUnknownKeyIsRefused(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// A family is named one by one, never by a wildcard, and only by the tool runner's module (ADR 0367 §2, §6):
|
||||
// each refusal is said in the manifest's words, at parse, rather than at the composition of the bus's users.
|
||||
func caseAWaitIsRefusedUnlessItNamesOneFamilyOfTheToolRunner(t *testing.T) {
|
||||
for manifest, want := range map[string]string{
|
||||
`{"module":"shop","version":"1.0","waits":["mesh-knowledge.reviewed"]}`: "only the tool runner's module",
|
||||
`{"module":"node-tools","version":"1.0","waits":["mesh-knowledge.reviewed"]}`: "only the tool runner's module", // its name says nothing (issue 774)
|
||||
`{"module":"node-tools","version":"1.0","tool-runner":true,"waits":["mesh-knowledge.*"]}`: "never a wildcard",
|
||||
`{"module":"node-tools","version":"1.0","tool-runner":true,"waits":["**"]}`: "never a wildcard",
|
||||
`{"module":"node-tools","version":"1.0","tool-runner":true,"waits":["mesh-knowledge.>"]}`: "never a wildcard",
|
||||
`{"module":"node-tools","version":"1.0","tool-runner":true,"waits":["*.reviewed"]}`: "never a wildcard",
|
||||
`{"module":"node-tools","version":"1.0","tool-runner":true,"waits":["reviewed"]}`: "does not name an emitter and an event",
|
||||
`{"module":"node-tools","version":"1.0","tool-runner":true,"waits":["mesh-knowledge..reviewed"]}`: "does not name an emitter and an event",
|
||||
`{"module":"node-tools","version":"1.0","tool-runner":true,"waits":["Mesh-Knowledge.reviewed x"]}`: "does not name an emitter and an event",
|
||||
`{"module":"node-tools","version":"1.0","tool-runner":true,"waits":["a.b","a.b"]}`: "twice",
|
||||
} {
|
||||
_, err := ParseManifest([]byte(manifest))
|
||||
if err == nil {
|
||||
t.Errorf("accepted: %s", manifest)
|
||||
continue
|
||||
}
|
||||
if !strings.Contains(err.Error(), want) {
|
||||
t.Errorf("%s refused for the wrong reason (want %q): %v", manifest, want, err)
|
||||
}
|
||||
// EE-D4 (design 34 every-event §10; ADR 0670 §2, ADR 0578 §1): the manifest no longer names what a session waits on, so
|
||||
// `waits` is a field the validator does not know: refused by the checker's Shelf naming it, set aside to wait by the
|
||||
// indexer's ShelfWaiting; the tool runner's manifest without it is accepted.
|
||||
func caseAManifestCarryingWaitsIsAFieldNotKnown(t *testing.T) {
|
||||
raws := map[string][]byte{
|
||||
"node-tools": []byte(`{"module":"node-tools","version":"1.0","tool-runner":true,"waits":["mesh-knowledge.reviewed"]}`),
|
||||
"runner": []byte(`{"module":"runner","version":"1.0","tool-runner":true}`),
|
||||
}
|
||||
if strict, _ := Shelf(raws, nil, 0); len(strict) != 1 || !strings.Contains(strings.Join(strict["node-tools"], " "), "waits") {
|
||||
t.Errorf("Shelf on a manifest carrying waits: %v", strict)
|
||||
}
|
||||
if refused, waits, _ := ShelfWaiting(raws, nil, 0, nil, nil); len(refused) != 0 ||
|
||||
!reflect.DeepEqual(waits, map[string][]string{"node-tools": {"waits"}}) {
|
||||
t.Errorf("ShelfWaiting on a manifest carrying waits: refused %v, waits %v", refused, waits)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6355,7 +6346,7 @@ func TestRulesBus(t *testing.T) {
|
||||
t.Run("AServedValueNamingSomethingTheMeshDoesNotHaveIsRefused", caseAServedValueNamingSomethingTheMeshDoesNotHaveIsRefused)
|
||||
t.Run("ASiteScopedProvisionIsRefused", caseASiteScopedProvisionIsRefused)
|
||||
t.Run("AStateNameIsLocalAndOneToken", caseAStateNameIsLocalAndOneToken)
|
||||
t.Run("AWaitIsRefusedUnlessItNamesOneFamilyOfTheToolRunner", caseAWaitIsRefusedUnlessItNamesOneFamilyOfTheToolRunner)
|
||||
t.Run("AManifestCarryingWaitsIsAFieldNotKnown", caseAManifestCarryingWaitsIsAFieldNotKnown)
|
||||
t.Run("AWorkQueueStreamIsReadByExactlyOneProcessOfItsModule", caseAWorkQueueStreamIsReadByExactlyOneProcessOfItsModule)
|
||||
t.Run("AWorkQueueStreamsValuesAreBounded", caseAWorkQueueStreamsValuesAreBounded)
|
||||
t.Run("AZoneMustNameOneOfTheModulesListens", caseAZoneMustNameOneOfTheModulesListens)
|
||||
|
||||
Reference in New Issue
Block a user