Publish only a commit on its module's trunk; post a pull request's change plan (hq ADR 0238)
mesh/merge-gate pass: the change touches no module of the mesh's graph
mesh/delivery delivered
mesh/delivery-group group feat/the-graph-decides-what-is-checked delivered: every member is delivered

One commit, one plan: a commit off the trunk — a pull request's head, a branch built by
hand, a rebuild or replay of one — is for checking. The build seat reads from its clone
which branches hold the commit, and the controller records and never registers a build
whose commit is not on the branch the module follows (the repository's default for a
new one), so nothing off the trunk can be sent.

A pull request's check now carries its change plan, computed by the planner: what a
merge would build in which order, what each machine would receive, and what is not an
ordinary send — the bus step, a module waiting for a person, a provider's consumers.
This commit is contained in:
jochen
2026-10-06 22:49:55 +02:00
parent 58ebe590a5
commit 3d05d74400
11 changed files with 481 additions and 3 deletions
+44
View File
@@ -330,3 +330,47 @@ func TestTheGateRunsWhenTheGraphIsTouchedBesideTheRepositorysOwnCheck(t *testing
t.Fatalf("a controller that does not build judged itself %+v", v.Gate)
}
}
// **Only a commit on the trunk is published** (novox/hq ADR 0238): the build seat reads, from the clone it
// just made, the branch the forge names its default and whether the commit built is on it.
func TestABuildSaysWhetherItsCommitIsOnTheTrunk(t *testing.T) {
repo, onMain := aCheckedRepository(t, map[string]string{"module.json": `{"module":"x","version":"1"}`})
git := func(dir string, args ...string) string {
cmd := exec.Command("git", args...)
cmd.Dir = dir
cmd.Env = append(os.Environ(), "GIT_AUTHOR_NAME=t", "GIT_AUTHOR_EMAIL=t@example.org",
"GIT_COMMITTER_NAME=t", "GIT_COMMITTER_EMAIL=t@example.org")
out, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("git %v: %v\n%s", args, err, out)
}
return strings.TrimSpace(string(out))
}
git(repo, "checkout", "--quiet", "-b", "feature")
if err := os.WriteFile(filepath.Join(repo, "x"), []byte("x"), 0o644); err != nil {
t.Fatal(err)
}
git(repo, "add", "-A")
git(repo, "commit", "--quiet", "-m", "off the trunk")
offMain := git(repo, "rev-parse", "HEAD")
git(repo, "checkout", "--quiet", "main")
clone := filepath.Join(t.TempDir(), "clone")
git(filepath.Dir(clone), "clone", "--quiet", repo, clone)
if trunk, on := trunkOf(t.Context(), Command, clone, onMain); trunk != "main" || !on {
t.Errorf("a commit on main reads as on %q: %v", trunk, on)
}
if trunk, on := trunkOf(t.Context(), Command, clone, offMain); trunk != "main" || on {
t.Errorf("a feature branch's commit reads as on %q: %v", trunk, on)
}
if got := strings.Join(branchesHolding(t.Context(), Command, clone, offMain), ","); got != "feature" {
t.Errorf("the feature branch's commit is said to be on %q", got)
}
if got := strings.Join(branchesHolding(t.Context(), Command, clone, onMain), ","); got != "feature,main" {
t.Errorf("main's commit is said to be on %q", got)
}
// A tree that says no trunk is not known — never read as on it.
if trunk, on := trunkOf(t.Context(), Command, repo, onMain); trunk != "" || on {
t.Errorf("a repository with no origin reads as trunk %q, on %v", trunk, on)
}
}