SD-fetch (the build ask's forms): fetch names builds, a built artifact its resolved packages, the toolchain its digest

Fetch.Builds, AskBuilt.Resolved and ToolchainUsed.Digest follow the build seats' part, which already names them.

Builds: design 47 G §465, §466

Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
This commit is contained in:
2026-11-11 20:33:56 +01:00
parent 28da5e08c3
commit 78c680ce1e
2 changed files with 53 additions and 0 deletions
+25
View File
@@ -242,6 +242,18 @@ type Fetch struct {
// member ({repository, commit, ref}).
Package *FetchPackage `json:"package,omitempty"`
Beside []FetchBeside `json:"beside,omitempty"`
// Builds name a group run's package members by their builds' digests (design 47 G §465): a package named here is named in
// neither Packages nor Package.
Builds []FetchBuild `json:"builds,omitempty"`
}
// FetchBuild is one package member of a group run by its build: the package's name in its ecosystem (the Go module path, the
// npm name), the member's module and artifact, and its build's `sha256:` digest (design 47 G §465).
type FetchBuild struct {
Package string `json:"package"`
Module string `json:"module"`
Artifact string `json:"artifact"`
Digest string `json:"digest"`
}
// FetchPackage is the group package a TypeScript fetch takes (ADR 0607 §3, ADR 0500 §5): either the group's tagged version
@@ -265,6 +277,9 @@ type ToolchainUsed struct {
Language string `json:"language"`
Recipe string `json:"recipe"`
Version string `json:"version"`
// Digest is the building node's digest of its toolchain program, the entry of kind 3 (design 47 G §466, §472), never the
// build module's own program.
Digest string `json:"digest,omitempty"`
}
// AskArtifact is one artifact of a build ask: built from the fetched tree, or copied from an upstream pin (From).
@@ -620,6 +635,16 @@ type AskBuilt struct {
Artifact string `json:"artifact"`
Digest string `json:"digest"`
Reference string `json:"reference,omitempty"`
// Resolved are the mesh packages the build resolved, one each, with the digest of the package's bytes as the build fetched
// them (design 47 G §466).
Resolved []AskResolved `json:"resolved,omitempty"`
}
// AskResolved is one mesh package a build resolved: its name, its version and the `sha256:` digest of its bytes.
type AskResolved struct {
Package string `json:"package"`
Version string `json:"version"`
Digest string `json:"digest"`
}
// CheckAnswer is what a check ask's step answers.
+28
View File
@@ -566,3 +566,31 @@ func TestTheThreeSeatsFixturesFitTheNeutralForms(t *testing.T) {
t.Errorf("only %d fixtures read", seen)
}
}
// 1966 (G §465, §466): a build ask's fetch names each package member's build, a built artifact the packages it resolved,
// and the toolchain the building node's digest, each read whole by the neutral forms.
func TestFetchBuildsResolvedAndToolchainDigestAreRead(t *testing.T) {
strict := func(raw string, into any) {
t.Helper()
dec := json.NewDecoder(strings.NewReader(raw))
dec.DisallowUnknownFields()
if err := dec.Decode(into); err != nil {
t.Error(err)
}
}
var job BuildJob
strict(`{"module":"m","fetch":{"repository":"r","commit":"c","builds":[{"package":"example.org/m/go","module":"m","artifact":"go-m","digest":"sha256:aa"}]},"artifacts":[]}`, &job)
if job.Fetch == nil || len(job.Fetch.Builds) != 1 || job.Fetch.Builds[0] != (FetchBuild{Package: "example.org/m/go", Module: "m", Artifact: "go-m", Digest: "sha256:aa"}) {
t.Errorf("fetch builds: %+v", job.Fetch)
}
var built AskBuilt
strict(`{"artifact":"go-m","digest":"sha256:bb","resolved":[{"package":"example.org/s/go","version":"0.1.4","digest":"sha256:cc"}]}`, &built)
if len(built.Resolved) != 1 || built.Resolved[0] != (AskResolved{Package: "example.org/s/go", Version: "0.1.4", Digest: "sha256:cc"}) {
t.Errorf("resolved: %+v", built)
}
var tc ToolchainUsed
strict(`{"language":"go","recipe":"r","version":"1.26.0","digest":"sha256:dd"}`, &tc)
if tc.Digest != "sha256:dd" {
t.Errorf("toolchain digest: %+v", tc)
}
}