DLV-I13: the judge reads a package series, a package's language and the contracts marker

Design 32's words: a series is <major>.<minor> and only on the four kinds the builder numbers, a package is go or
typescript, generated-from only on a package. A package is published as its source, so it names no system: today's
judge refused mesh-sdk's Go package (no system) as a binary.

Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
This commit is contained in:
2026-11-04 14:01:38 +01:00
parent 87ba69ed69
commit 20a9322209
2 changed files with 55 additions and 2 deletions
+35 -2
View File
@@ -208,6 +208,37 @@ func upstreamFileProblems(module string, a catalogue.Artifact) []string {
return problems
}
// seriesForm is a package series, `<major>.<minor>` (design 32).
var seriesForm = regexp.MustCompile(`^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$`)
// seriesProblems are an artifact's refusals of the words of design 32's versions (DLV-I13; ADR 0606 §4, ADR 0608 §5): a
// package series well formed and only on the four kinds the builder numbers, a package in Go or TypeScript, and the
// contracts marker only on a package.
func seriesProblems(module string, a catalogue.Artifact) []string {
var problems []string
if a.Series != "" {
if !seriesForm.MatchString(a.Series) {
problems = append(problems, fmt.Sprintf("%s: %q names the package series %q, which is no <major>.<minor> such as 0.1 (design 32)",
module, a.Name, a.Series))
}
switch a.Kind {
case catalogue.ArtifactPackage, catalogue.ArtifactImage, catalogue.ArtifactBundle, catalogue.ArtifactArchive:
default:
problems = append(problems, fmt.Sprintf("%s: %q is a %q and names a package series; only a package, an image, a bundle "+
"or an archive is numbered (design 32)", module, a.Name, a.Kind))
}
}
if a.Kind == catalogue.ArtifactPackage && a.Language != "" && a.Language != "go" && a.Language != "typescript" {
problems = append(problems, fmt.Sprintf("%s: %q is a package in %q; a mesh package is go or typescript (design 32)",
module, a.Name, a.Language))
}
if a.GeneratedFrom != "" && a.Kind != catalogue.ArtifactPackage {
problems = append(problems, fmt.Sprintf("%s: %q is a %q and names generated-from, the contracts marker, which only a "+
"package carries (design 26)", module, a.Name, a.Kind))
}
return problems
}
// checkBuild is the manifest's own account of what it builds.
func buildProblems(b *catalogue.Build, module string) []string {
if b == nil {
@@ -234,6 +265,7 @@ func buildProblems(b *catalogue.Build, module string) []string {
module, a.Name, a.Kind, catalogue.ArtifactImage, catalogue.ArtifactArchive, catalogue.ArtifactUpstream,
catalogue.ArtifactBundle+", "+catalogue.ArtifactPackage))
}
problems = append(problems, seriesProblems(module, a)...)
// **A bundle is built from the module itself, so it says a language instead.** Everything
// else names what it is built from: a Dockerfile, a directory, somebody else's reference.
// A bundle's source is the module's own directory by definition, and what it needs to say
@@ -293,8 +325,9 @@ func buildProblems(b *catalogue.Build, module string) []string {
// is pinned to one operating system at link time so a host refuses to touch a machine
// it was not built for (novox/hq ADR 0005); an artifact that says nothing would be
// compiled for whatever the build machine happened to be, which reads as portable and
// is not.
if compiled := compilesToABinary(a.Language); compiled && strings.TrimSpace(a.System) == "" {
// is not. A package is published as its source (a Go module, an npm package; ADR 0606 §1), never as a binary,
// so it names no system whatever its language.
if compiled := compilesToABinary(a.Language) && a.Kind != catalogue.ArtifactPackage; compiled && strings.TrimSpace(a.System) == "" {
problems = append(problems, fmt.Sprintf(
"%s: %q is compiled to a binary and says no system, so it would be built for "+
"whatever the build machine happens to be. Declare one artifact per "+
@@ -2328,6 +2328,26 @@ func TestAPackageParsesLikeABundleAndNeedsALanguage(t *testing.T) {
{"name":"lib","kind":"package"}]}}`)); err == nil {
t.Fatal("a package with no language was accepted")
}
// 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.
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"}`, ""},
{`{"name":"go","kind":"package","language":"go","paths":["go"],"series":"0.1.3"}`, `names the package series "0.1.3"`},
{`{"name":"go","kind":"package","language":"go","paths":["go"],"series":"01.1"}`, `names the package series "01.1"`},
{`{"name":"up","kind":"upstream","from":"redis:7","series":"0.1"}`, `is a "upstream" and names a package series`},
{`{"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`},
} {
_, err := ParseManifest([]byte(`{"module":"a","version":"1","build":{"artifacts":[` + c.artifact + `]}}`))
switch {
case c.refused == "" && err != nil:
t.Errorf("%s refused: %v", c.artifact, err)
case c.refused != "" && (err == nil || !strings.Contains(err.Error(), c.refused) || !strings.Contains(err.Error(), "a:")):
t.Errorf("%s: %v, want refused naming %q", c.artifact, err, c.refused)
}
}
}
func TestAPathThroughAnAccessIsJudgedWithTheAccessFilledIn(t *testing.T) {