DLV-I16: the judge refuses a contracts module claiming a seat, naming the seat

A module whose package carries generated-from holds contracts only (design 26).

Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
This commit is contained in:
2026-11-04 14:06:03 +01:00
parent 2e5917535c
commit ea6fbd31db
2 changed files with 35 additions and 1 deletions
@@ -239,6 +239,30 @@ func seriesProblems(module string, a catalogue.Artifact) []string {
return problems
}
// contractsProblems refuses a contracts module that claims a seat, naming each seat (DLV-I16; ADR 0608 §5, design 26
// *Contracts modules*): a module whose package carries the contracts marker, generated-from, holds contracts only.
func contractsProblems(m catalogue.Manifest) []string {
if m.Build == nil || len(m.Claims) == 0 {
return nil
}
marked := ""
for _, a := range m.Build.Artifacts {
if a.GeneratedFrom != "" {
marked = a.Name
break
}
}
if marked == "" {
return nil
}
var problems []string
for _, c := range m.Claims {
problems = append(problems, fmt.Sprintf("%s: its package %q carries generated-from, so it is a contracts module, which "+
"holds contracts only and claims no seat; it claims %s (design 26)", m.Module, marked, c.Name))
}
return problems
}
// checkBuild is the manifest's own account of what it builds.
func buildProblems(b *catalogue.Build, module string) []string {
if b == nil {
@@ -2792,6 +2816,7 @@ func parseManifest(raw []byte, predefined catalogue.PredefinedList) (catalogue.M
}
}
problems = append(problems, buildProblems(m.Build, m.Module)...)
problems = append(problems, contractsProblems(m)...)
// A file's text in a template file of the module's repository (novox/hq ADR 0349 §2): only a file, never beside
// content, only under files/, and packed by the module's build.
problems = append(problems, templateProblems(m)...)
@@ -2330,6 +2330,7 @@ func TestAPackageParsesLikeABundleAndNeedsALanguage(t *testing.T) {
}
// DLV-I13 (design 32 *A package, its series*): a series is <major>.<minor> on the four numbered kinds; a package is go or
// typescript; the contracts marker is a package's.
const claims = " claiming mesh-vault"
for _, c := range []struct{ artifact, refused string }{
{`{"name":"go","kind":"package","language":"go","paths":["go"],"series":"0.2"}`, ""},
{`{"name":"img","kind":"image","from":"Dockerfile","series":"1.0"}`, ""},
@@ -2339,8 +2340,16 @@ func TestAPackageParsesLikeABundleAndNeedsALanguage(t *testing.T) {
{`{"name":"go","kind":"package","language":"go","paths":["go"],"system":"arch"}`, `names the system "arch"`},
{`{"name":"py","kind":"package","language":"python"}`, `a mesh package is go or typescript`},
{`{"name":"img","kind":"image","from":"Dockerfile","generated-from":"seats"}`, `only a package carries`},
{`{"name":"go","kind":"package","language":"go","paths":["go"],"generated-from":"."}`, ""},
// DLV-I16 (design 26): a contracts module claims no seat, refused naming it.
{`{"name":"go","kind":"package","language":"go","paths":["go"],"generated-from":"."}` + claims,
`a contracts module, which holds contracts only and claims no seat; it claims mesh-vault`},
} {
_, err := ParseManifest([]byte(`{"module":"a","version":"1","build":{"artifacts":[` + c.artifact + `]}}`))
raw := `{"module":"a","version":"1","build":{"artifacts":[` + c.artifact + `]}}`
if before, ok := strings.CutSuffix(c.artifact, claims); ok {
raw = `{"module":"a","version":"1","claims":[{"name":"mesh-vault","scope":"mesh"}],"build":{"artifacts":[` + before + `]}}`
}
_, err := ParseManifest([]byte(raw))
switch {
case c.refused == "" && err != nil:
t.Errorf("%s refused: %v", c.artifact, err)