JUDGE (A-30, §529): a foundation part's own findings stream <module>-findings is a predefined form; the bus fixture serves §681's snapshot verbs

rules.go keptUntilMoved: the stream FindingStreamOf(module) of a foundation module is not refused as outside the predefined forms (the judge's own gwords.go requires it of a foundation part, A-30 says it stays in the old streams section). rules_test.go: rows in caseTwoModulesCannotDeclareOneStream (fails without the change), and caseTheMeshsOwnSeatsAreStillClaimable names snapshot-get, snapshot-restore, snapshot-restore-cancel, snapshot-remove (§681) instead of snapshot-kept and restore-kept (§554, mesh-recovery's).

Builds: design 47 G §529, §681, A-30

Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
This commit is contained in:
2026-11-11 22:41:39 +01:00
parent 1cad83bad7
commit 395c53e63f
2 changed files with 14 additions and 1 deletions
@@ -5567,6 +5567,10 @@ var seatStreamsKeptUntilMoved = map[string][]string{
// keptUntilMoved is whether a stream of a manifest is one kept until its module moves it: by the module's name, or by a
// seat it claims.
func keptUntilMoved(m catalogue.Manifest, stream string) bool {
// A foundation part says its findings on its old stream `<module>-findings` for good (design 47 G §529, A-30).
if stream == FindingStreamOf(m.Module) && slices.Contains(Foundation, m.Module) {
return true
}
if slices.Contains(streamsKeptUntilMoved[m.Module], stream) {
return true
}
@@ -4683,7 +4683,7 @@ func caseTheMeshsOwnSeatsAreStillClaimable(t *testing.T) {
// It delivers the bus, so its holder provides the bus — the rule this check now enforces.
m := catalogue.Manifest{Module: "nats",
Provides: []catalogue.Offer{{Name: "mesh-bus", Scope: catalogue.ScopeMesh, Credential: &catalogue.OfferCredential{Form: catalogue.CredentialFormNone}}},
Claims: []catalogue.Claim{{Name: "mesh-broker", Scope: catalogue.ScopeMesh, Serves: []string{"snapshot-kept", "restore-kept"}}}}
Claims: []catalogue.Claim{{Name: "mesh-broker", Scope: catalogue.ScopeMesh, Serves: []string{"snapshot-get", "snapshot-restore", "snapshot-restore-cancel", "snapshot-remove"}}}}
if got := problemsFor(t, catalogue.Shelf{"nats": m}); got != "" {
t.Fatalf("a mesh seat was refused by the derived check: %s", got)
}
@@ -5121,6 +5121,15 @@ func caseTwoModulesCannotDeclareOneStream(t *testing.T) {
if got := PredefinedFormProblems(catalogue.Manifest{Module: "mesh-build-go", Streams: toolchains}); len(got) != 1 {
t.Fatalf("a toolchain stream of a module claiming no build seat was kept by its name: %v", got)
}
// A foundation part says its findings on its old stream `<module>-findings` for good (design 47 G §529, A-30); a part
// that is no foundation part keeps none (its findings go by the template `events`).
findings := []catalogue.StreamDeclaration{{Name: "mesh-config-findings", Events: []string{"finding-written.*"}}}
if got := PredefinedFormProblems(catalogue.Manifest{Module: "mesh-config", Streams: findings}); len(got) != 0 {
t.Fatalf("a foundation part's findings stream was refused: %v", got)
}
if got := PredefinedFormProblems(catalogue.Manifest{Module: "mesh-config-b", Streams: []catalogue.StreamDeclaration{{Name: "mesh-config-b-findings", Events: []string{"finding-written.*"}}}}); len(got) != 1 {
t.Fatalf("a findings stream of a part outside the foundation was kept: %v", got)
}
}
// A seat name meaning two protocols is the failure nobody could diagnose afterwards.