Join item 6: the builder says version.numbered as delivery.VersionNumbered and reads out-of-step by BuildAnswer's field

versions.NumberedBody and NumberedEvent are mesh-sdk's delivery.VersionNumbered and VersionNumberedEvent now (J3), the
contract a build module consumes for BG2's late publish; the body's JSON is unchanged. The lane reads a step's
out-of-step files through delivery.BuildAnswer.OutOfStep, a failed step's result too (as before, A2k's d15d66fc: read
before the step's state; its three rows hold it), in place of a local decode by name. The integration test hears
version.numbered on delivery.VersionNumberedSubject and reads it with DecodeVersionNumbered, as a build module does.

Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
This commit is contained in:
2026-11-04 15:12:13 +01:00
parent 91b24a5426
commit 7ae4f2bb7f
10 changed files with 35 additions and 48 deletions
@@ -1141,7 +1141,7 @@ type registry struct {
b *bed
versions, findings, reasks jetstream.KeyValue
mu sync.Mutex
numbered []versions.NumberedBody
numbered []delivery.VersionNumbered
removes []map[string]any
}
@@ -1189,9 +1189,9 @@ func (b *bed) registry(t *testing.T, node string, seatVersions ...string) *regis
t.Fatal(err)
}
nc := b.js.Conn()
sub, err := nc.Subscribe("mesh.mod."+delivery.BuilderModule+".event."+versions.NumberedEvent, func(m *nats.Msg) {
var nb versions.NumberedBody
if json.Unmarshal(m.Data, &nb) == nil {
// As a build module hears it: on the contract's subject, read by the contract's decoder (BG2's late publish).
sub, err := nc.Subscribe(delivery.VersionNumberedSubject, func(m *nats.Msg) {
if nb, err := delivery.DecodeVersionNumbered(m.Data); err == nil {
r.mu.Lock()
r.numbered = append(r.numbered, nb)
r.mu.Unlock()
@@ -148,7 +148,7 @@ func run(ctx context.Context, getenv func(string) string, logOut io.Writer) erro
packagesKV := process.AwaitBucket(ctx, js, conn, delivery.PackagesBucket, "no package is numbered: each is built unnumbered and said", logger.Printf)
numberer := &versions.Numberer{Versions: versions.Versions{Store: awaitedVersions{versionsKV}}, Floor: floorVia(calls.Call), Waits: floorWaits,
Names: versions.NamesIn(indexerPackages{packagesKV}),
Said: func(nb versions.NumberedBody) {
Said: func(nb delivery.VersionNumbered) {
if err := emitNumbered(context.WithoutCancel(ctx), js, cred, nb); err != nil {
logger.Printf("%v", err)
}
@@ -186,13 +186,13 @@ func floorVia(call toolCaller) versions.FloorSources {
// emitNumbered says the builder's event version.numbered (design 51 *Events of the builder*), on its own family apart
// from its builds' ends; the name and version are the bus's dedup id.
func emitNumbered(ctx context.Context, js jetstream.JetStream, cred process.Account, b versions.NumberedBody) error {
func emitNumbered(ctx context.Context, js jetstream.JetStream, cred process.Account, b delivery.VersionNumbered) error {
id := "numbered-" + versions.Key(b.Name, b.Version)
if b.Again != "" {
id += "-again-" + b.Again
}
if err := emitEvent(ctx, js, cred, versions.NumberedEvent, id, b); err != nil {
return fmt.Errorf("saying %s for %s@%s: %w", versions.NumberedEvent, b.Name, b.Version, err)
if err := emitEvent(ctx, js, cred, delivery.VersionNumberedEvent, id, b); err != nil {
return fmt.Errorf("saying %s for %s@%s: %w", delivery.VersionNumberedEvent, b.Name, b.Version, err)
}
return nil
}
@@ -3,11 +3,12 @@ package build
import (
"errors"
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-builder/buildrun"
"git.novox.be/novox/mesh-sdk/go/delivery"
"strings"
"testing"
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-builder/buildrun"
"git.novox.be/novox/mesh-sdk/go/delivery"
"git.novox.be/novox/mesh-sdk/go/catalogue"
)
@@ -2,9 +2,10 @@ package build
import (
"context"
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-builder/buildrun"
"testing"
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-builder/buildrun"
"git.novox.be/novox/mesh-sdk/go/catalogue"
"git.novox.be/novox/mesh-sdk/go/delivery"
)
@@ -905,11 +905,8 @@ func (b *Builder) runLane(ctx context.Context, l *lane, repository string, m del
}
l.node = step.Node
// The build module's compare of a contracts module's generated files (design 26, CAT-BG5/BN2) answers the files out
// of step as `out-of-step`, in a failed step's result too. Read beside the build's answer: the SDK's BuildAnswer
// names no such field yet (a request for mesh-sdk), so it is read by its name and shape here.
var compared struct {
OutOfStep []string `json:"out-of-step"`
}
// of step as delivery.BuildAnswer.OutOfStep, in a failed step's result too: read before the step's state is.
var compared delivery.BuildAnswer
if len(step.Result) > 0 && json.Unmarshal(step.Result, &compared) == nil {
l.outOfStep = compared.OutOfStep
}
@@ -8,6 +8,8 @@ import (
"sort"
"strings"
"time"
"git.novox.be/novox/mesh-sdk/go/delivery"
)
// What builder_publish_again does with one fingerprint of a name (design 51 *Tools of the builder*), after a holder failed.
@@ -289,7 +291,7 @@ func (a Acts) PublishAgain(ctx context.Context, name, fp, why, by string, at tim
b.Again = at.UTC().Format(time.RFC3339Nano)
a.Numberer.Said(b)
}
answer += "; " + NumberedEvent + " said for " + ag.Entry.Version
answer += "; " + delivery.VersionNumberedEvent + " said for " + ag.Entry.Version
}
return ag, answer, nil
}
@@ -6,6 +6,8 @@ import (
"sort"
"strings"
"time"
"git.novox.be/novox/mesh-sdk/go/delivery"
)
// The registry seats a version is published to (design 51 *The seats*), by what is published.
@@ -133,7 +135,7 @@ type Numberer struct {
// Holder is the module holding a seat, whose health condition's clear wakes a silent seat source; nil names none.
Holder func(seat string) string
// Said is told each version newly numbered; nil tells nobody.
Said func(NumberedBody)
Said func(delivery.VersionNumbered)
// Names answers a package's name in its ecosystem; nil numbers a package as NameOf names it.
Names PackageNames
Now func() time.Time
@@ -6,6 +6,8 @@ import (
"errors"
"fmt"
"strings"
"git.novox.be/novox/mesh-sdk/go/delivery"
)
// The builder's tools of its versions (design 51 *Events of the builder*, *Tools of the builder*).
@@ -17,33 +19,14 @@ const (
TagAsksTool = "builder_tag_asks"
UntagTool = "builder_untag"
OldFormTool = "builder_old_form"
// NumberedEvent and OldFormClosedEvent are the builder's own family `version`, kept seven days, apart from its builds'
// ends, so a waiter on a build's end does not wake on them.
NumberedEvent = "version.numbered"
// OldFormClosedEvent is, with delivery.VersionNumberedEvent, the builder's own family `version`, kept seven days,
// apart from its builds' ends, so a waiter on a build's end does not wake on them.
OldFormClosedEvent = "version.old-form-closed"
)
// NumberedBody is the body of NumberedEvent: what a build module consumes to publish a build's version with the held digest,
// which stores nothing (design 51 *The floor*).
type NumberedBody struct {
Name string `json:"name"`
Kind string `json:"kind"`
Version string `json:"version"`
Tag string `json:"tag,omitempty"`
Module string `json:"module"`
Fingerprint string `json:"fingerprint"`
Commit string `json:"commit,omitempty"`
Digest string `json:"digest,omitempty"`
Seat string `json:"seat,omitempty"`
// Head is the head the version answers, when it answers a tag ask.
Head string `json:"head,omitempty"`
// Again is when builder_publish_again said it once more, so the bus's dedup does not drop it.
Again string `json:"again,omitempty"`
}
// NumberedOf is the event of an entry.
func NumberedOf(e Entry, head string) NumberedBody {
return NumberedBody{Name: e.Name, Kind: e.Kind, Version: e.Version, Tag: e.Tag, Module: e.Module, Fingerprint: e.Fingerprint,
// NumberedOf is the version.numbered body of an entry (delivery.VersionNumbered, the contract a build module reads).
func NumberedOf(e Entry, head string) delivery.VersionNumbered {
return delivery.VersionNumbered{Name: e.Name, Kind: e.Kind, Version: e.Version, Tag: e.Tag, Module: e.Module, Fingerprint: e.Fingerprint,
Commit: e.Commit, Digest: e.Digest, Seat: e.Seat, Head: head}
}
@@ -13,6 +13,7 @@ import (
"time"
"git.novox.be/novox/mesh-delivery/sdk/forms"
"git.novox.be/novox/mesh-sdk/go/delivery"
)
// mem is a Store in memory; before runs once before the next Create, to stage a race.
@@ -379,9 +380,9 @@ func TestTheBuildersVersions(t *testing.T) {
},
Requirements: func(context.Context, string) ([]string, error) { return nil, nil },
}
var said []NumberedBody
var said []delivery.VersionNumbered
fw := &FloorWaits{}
n := &Numberer{Versions: Versions{Store: newMem()}, Floor: src, Waits: fw, Said: func(b NumberedBody) { said = append(said, b) }}
n := &Numberer{Versions: Versions{Store: newMem()}, Floor: src, Waits: fw, Said: func(b delivery.VersionNumbered) { said = append(said, b) }}
c := BuildClaim{Module: "m", Path: "go", Repository: "novox/m", Fingerprint: "fp1", Commit: "c1", Revision: "7", Merge: 7,
Artifacts: []ClaimArtifact{{Artifact: "program", Kind: KindBundle, Language: "go"}, {Artifact: "base", Kind: "upstream"}}}
got, err := n.Number(ctx, c)
@@ -473,8 +474,8 @@ func TestTheBuildersVersions(t *testing.T) {
return nil, nil
},
}
var said []NumberedBody
n := &Numberer{Versions: Versions{Store: newMem()}, Floor: src, Names: NamesIn(state), Said: func(b NumberedBody) { said = append(said, b) }}
var said []delivery.VersionNumbered
n := &Numberer{Versions: Versions{Store: newMem()}, Floor: src, Names: NamesIn(state), Said: func(b delivery.VersionNumbered) { said = append(said, b) }}
c := BuildClaim{Module: "mesh-sdk", Path: "go", Repository: "novox/mesh-sdk", Fingerprint: "fp1", Commit: "c1", Revision: "3", Merge: 3,
Artifacts: []ClaimArtifact{{Artifact: "go", Kind: KindPackage, Language: "go"}, {Artifact: "ts", Kind: KindPackage, Language: "typescript"},
{Artifact: "new", Kind: KindPackage, Language: "go"}, {Artifact: "program", Kind: KindBundle, Language: "go"}}}
@@ -599,10 +600,10 @@ func TestTheBuildersVersions(t *testing.T) {
t.Error("a version refused for other bytes is published again")
}
_, _ = v.Mark(ctx, "m/p", "0.1.4", func(e *Entry) { e.State = Published })
var said []NumberedBody
var said []delivery.VersionNumbered
var rebuilt []string
done := true
acts := Acts{Numberer: &Numberer{Versions: v, Said: func(b NumberedBody) { said = append(said, b) }, Waits: &FloorWaits{}},
acts := Acts{Numberer: &Numberer{Versions: v, Said: func(b delivery.VersionNumbered) { said = append(said, b) }, Waits: &FloorWaits{}},
Done: func(context.Context, string, string) (bool, error) { return done, nil },
BuildAgain: func(_ context.Context, m, fp, _, _ string) (string, bool) {
rebuilt = append(rebuilt, m+" "+fp)