From b7e251a46394a6cf759cd7df0acd0681c43d7d55 Mon Sep 17 00:00:00 2001 From: jochen Date: Thu, 12 Nov 2026 06:27:42 +0100 Subject: [PATCH] B5g3-1: a run's input is any size, RunInputBound goes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Builds: design 47 G §712, §354, A-237 Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h --- .../cmd/mesh-checking-program/main_test.go | 14 +++++++------- modules/mesh-delivery-checker/rules/seats.go | 4 ++-- .../mesh-delivery-sdk/buildstep/ask_test.go | 7 ++++--- modules/mesh-delivery-sdk/buildstep/run.go | 18 +++++------------- 4 files changed, 18 insertions(+), 25 deletions(-) diff --git a/modules/mesh-delivery-checker/cmd/mesh-checking-program/main_test.go b/modules/mesh-delivery-checker/cmd/mesh-checking-program/main_test.go index cbd54007..972fa7d8 100644 --- a/modules/mesh-delivery-checker/cmd/mesh-checking-program/main_test.go +++ b/modules/mesh-delivery-checker/cmd/mesh-checking-program/main_test.go @@ -153,8 +153,8 @@ func TestTheCheckingProgramAnswersTheVerdictOfItsFacts(t *testing.T) { } // Review finding 3 of milestone 47/G: the heads of a real group carry every seat definition the reader holds, unchanged // (this repository's own contracts, laid as its head): the answer leaves them all to the checker's list and stays - // within the bound a run's answer is written under (buildstep.RunInputBound), where the whole list would not. - t.Run("heads carrying every definition the reader holds unchanged answer none of them, within the bound", func(t *testing.T) { + // far below the whole list. + t.Run("heads carrying every definition the reader holds unchanged answer none of them", func(t *testing.T) { real := under{prefix: "novox/mesh-delivery", fs: os.DirFS("../../../..")} group := rules.Facts{V: rules.FactsVersion, Members: []rules.Member{{Repository: "novox/mesh-delivery", Head: "h"}}} // An empty list of digests answers every definition whole (a checker that hands its list's digests, holding none). @@ -166,9 +166,9 @@ func TestTheCheckingProgramAnswersTheVerdictOfItsFacts(t *testing.T) { group.SeatDigests = wholeDigests(t, real, "novox/mesh-delivery") same, err := rules.SeatsOf(real, group) answer, _ := json.Marshal(same) - if err != nil || len(same.Seats) != 0 || same.Same != len(whole.Seats) || len(answer) > buildstep.RunInputBound { - t.Errorf("unchanged heads answer %d definitions (%d the same), %d bytes; want none, all %d the same, within %d: %v", - len(same.Seats), same.Same, len(answer), len(whole.Seats), buildstep.RunInputBound, err) + if err != nil || len(same.Seats) != 0 || same.Same != len(whole.Seats) { + t.Errorf("unchanged heads answer %d definitions (%d the same), %d bytes; want none, all %d the same: %v", + len(same.Seats), same.Same, len(answer), len(whole.Seats), err) } // Review round 2 of G: a checker from before G (B0's, which makes G's own check) hands no digests, and the answer // then keeps each seat's own description only, so a group's whole list stays within the bound; each still parses. @@ -206,8 +206,8 @@ func TestTheCheckingProgramAnswersTheVerdictOfItsFacts(t *testing.T) { t.Errorf("B0-shaped facts answer %s with %d inner descriptions, its own %q: %v; want only its own", raw[:min(len(raw), 80)], inner, d.Description, perr) } } - if answer, _ := json.Marshal(b0); len(answer) > buildstep.RunInputBound || len(answer) >= len(mustJSON(t, whole))*3/4 { - t.Errorf("B0-shaped facts answer %d bytes (whole %d), want within %d and far below the whole", len(answer), len(mustJSON(t, whole)), buildstep.RunInputBound) + if answer, _ := json.Marshal(b0); len(answer) >= len(mustJSON(t, whole))*3/4 { + t.Errorf("B0-shaped facts answer %d bytes (whole %d), want far below the whole", len(answer), len(mustJSON(t, whole))) } // One definition the heads change is answered alone. for seat := range group.SeatDigests { diff --git a/modules/mesh-delivery-checker/rules/seats.go b/modules/mesh-delivery-checker/rules/seats.go index 1e3a37c8..50040e14 100644 --- a/modules/mesh-delivery-checker/rules/seats.go +++ b/modules/mesh-delivery-checker/rules/seats.go @@ -21,8 +21,8 @@ import ( // milestones 47/B0 and 47/G): the checking program built from the heads reads the definitions the heads' contracts // modules carry, by the domain SDK's one reading (sdk/seatdefs), the indexer's too, and answers them; the running checker // lays them by seat over the list its reader holds from the seat mesh-catalog (verb seat-definitions) and reads no file -// of the heads. The reader's list is not in the program's input: the mesh's definitions are larger than a run input's -// bound (buildstep.RunInputBound). +// of the heads. The reader's list is not in the program's input: it is large, and the answer carries only what the heads +// change. // SeatsVersion is the version of SeatsAnswer this program writes. const SeatsVersion = 1 diff --git a/modules/mesh-delivery-sdk/buildstep/ask_test.go b/modules/mesh-delivery-sdk/buildstep/ask_test.go index 7676d0f4..258b5215 100644 --- a/modules/mesh-delivery-sdk/buildstep/ask_test.go +++ b/modules/mesh-delivery-sdk/buildstep/ask_test.go @@ -113,7 +113,7 @@ func TestAskCheckAndRoundTrip(t *testing.T) { {"input on a state", func(a *StepAsk) { a.Run.Input.Verb = "mesh-delivery-checker.inputs" }, "no seat:."}, {"input on one machine", func(a *StepAsk) { a.Run.Input.Verb = "seat:mesh-delivery-checker.input@ace" }, "no seat:."}, {"input by no digest", func(a *StepAsk) { a.Run.Input.Digest = "d1" }, "no sha256 digest"}, - {"input over its bound", func(a *StepAsk) { a.Run.Input.Size = RunInputBound + 1 }, "outside 1 to"}, + {"input of no bytes", func(a *StepAsk) { a.Run.Input.Size = 0 }, "under 1"}, {"argument of the shell", func(a *StepAsk) { a.Run.Args = []string{"-x; rm"} }, "no word or flag"}, } { a := runAsk() @@ -148,8 +148,9 @@ func TestAskCheckAndRoundTrip(t *testing.T) { if a := stepAsk(); !a.Step.Skips("./modules/nats/a", "sha256:bbbb") || a.Step.Skips("./modules/nats/a", "sha256:cccc") { t.Error("a kept result skips its package at its digest and level only") } - if _, err := RunInputOf("seat:mesh-delivery-checker.input", make([]byte, RunInputBound+1)); err == nil || !strings.Contains(err.Error(), "262145 bytes") { - t.Errorf("an input over its bound: %v", err) + // A-237: a run's input is any size. + if in, err := RunInputOf("seat:mesh-delivery-checker.input", make([]byte, 3<<20)); err != nil || in.Size != 3<<20 { + t.Errorf("an input of 3 MiB: %+v, %v", in, err) } in := runAsk().Run.Input if err := in.Verify([]byte(`{"v":1}`)); err != nil { diff --git a/modules/mesh-delivery-sdk/buildstep/run.go b/modules/mesh-delivery-sdk/buildstep/run.go index c98c6262..c69879b7 100644 --- a/modules/mesh-delivery-sdk/buildstep/run.go +++ b/modules/mesh-delivery-sdk/buildstep/run.go @@ -20,8 +20,8 @@ import ( // Input names, checks its digest and writes it to the file RunInputEnv names; then runs the program with Args, no // network and no bus account (ADR 0448 §2, §4), and answers RunAnswer on its step key. // -// The input is carried by reference, as a compose carries its manifests: the asker keeps it by its digest, measured -// against RunInputBound before it asks, and serves it on a verb of its seat (RunInput.Verb); the build module asks that +// The input is carried by reference, as a compose carries its manifests: the asker keeps it by its digest, of any +// size (A-237), and serves it on a verb of its seat (RunInput.Verb); the build module asks that // verb as its manifest's `invokes` grants it, never reading the asker's state (ADR 0596 §2), so the ask on the stream // never carries it (issue 1930). The layouts are the part build-step's `RunJob`, `RunProgram`, `RunHead`, `RunInput` // and `RunAnswer`. @@ -77,22 +77,14 @@ type RunAnswer struct { Said string `json:"said,omitempty"` } -// RunInputBound is the most bytes a run's input may hold: the bus's value limit the design already uses (256 KiB), so -// the asker keeps it as one value (the lead's ruling on milestone 47/B0, 2026-11-06). -const RunInputBound = 256 << 10 - // RunHeadsEnv names, for the program, the directory its heads are laid in; RunInputEnv the file its input is written to. const ( RunHeadsEnv = "MESH_RUN_HEADS" RunInputEnv = "MESH_RUN_INPUT" ) -// RunInputOf is the reference to body served on verb (`seat:.`), refusing a body over RunInputBound, naming -// its size, so an asker refuses it before asking. +// RunInputOf is the reference to body served on verb (`seat:.`); a body is of any size. func RunInputOf(verb string, body []byte) (RunInput, error) { - if len(body) > RunInputBound { - return RunInput{}, fmt.Errorf("buildstep: a run's input of %d bytes is over its bound of %d bytes", len(body), RunInputBound) - } sum := sha256.Sum256(body) in := RunInput{Verb: verb, Digest: hex.EncodeToString(sum[:]), Size: len(body)} return in, in.check("") @@ -118,8 +110,8 @@ func (i RunInput) check(id string) error { return fmt.Errorf("buildstep: the run ask %s serves its input on %q, which is no seat:. of no one machine", id, i.Verb) case !runDigestOK.MatchString(i.Digest): return fmt.Errorf("buildstep: the run ask %s names its input by %q, which is no sha256 digest", id, i.Digest) - case i.Size <= 0 || i.Size > RunInputBound: - return fmt.Errorf("buildstep: the run ask %s names an input of %d bytes, outside 1 to %d", id, i.Size, RunInputBound) + case i.Size <= 0: + return fmt.Errorf("buildstep: the run ask %s names an input of %d bytes, under 1", id, i.Size) } return nil }