Merge pull request 'ADR 0238: a commit is the build at hand — one commit, one change plan, checked off the trunk and published only on it' (#155) from design/0238-one-commit-one-change-plan into main
This commit was merged in pull request #155.
This commit is contained in:
+8
@@ -9,6 +9,14 @@ extends: 02-DECISIONS/0227-the-core-holds-nine-rules-each-checked-and-is-built-t
|
||||
|
||||
# 237. A change is judged against the mesh that runs, before it merges, on the build seat
|
||||
|
||||
> **Narrowed, not replaced — 2026-10-06, by [ADR 0238](0238-a-commit-is-the-build-at-hand-one-commit-one-change-plan-checked-off-the-trunk-and-published-only-on-it.md).**
|
||||
> Decision 4's *which* and *what* moved: a pull request is checked when the mesh's module graph says it
|
||||
> reaches a module — the planner's own answer, not *a repository it builds a module from into that
|
||||
> branch* — and every repository of the mesh runs its own `merge-check.sh` as a second status,
|
||||
> `mesh/repo-check`, a warning when it has none, instead of *the gate alone*. The gate itself is the
|
||||
> build seat's, no longer each repository's script. The facts, the gate's rules, the replays, where a
|
||||
> check runs and what it is given stand as decided here.
|
||||
|
||||
## Context
|
||||
|
||||
**The operator approved starting Phase 5** of [to-be 45](../03-DESIGN/01-to-be/45-a-core-that-cannot-fail-silently.md)
|
||||
|
||||
+186
@@ -0,0 +1,186 @@
|
||||
---
|
||||
topic: the mesh
|
||||
status: accepted
|
||||
date: 2026-10-06
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
supersedes-in-part:
|
||||
- 0237-a-change-is-judged-against-the-mesh-that-runs-before-it-merges-on-the-build-seat.md
|
||||
extends: 02-DECISIONS/0237-a-change-is-judged-against-the-mesh-that-runs-before-it-merges-on-the-build-seat.md
|
||||
---
|
||||
|
||||
# 238. A commit is the build at hand: one commit, one change plan, checked off the trunk and published only on it
|
||||
|
||||
## Context
|
||||
|
||||
[ADR 0237](0237-a-change-is-judged-against-the-mesh-that-runs-before-it-merges-on-the-build-seat.md) put a
|
||||
check before every merge and ran it on the build seat. Turning it on for every repository of the mesh, the
|
||||
same day, showed four places where it asked the wrong question.
|
||||
|
||||
- **Which pull requests are checked was the repository's choice, not the mesh's.** The controller checked a
|
||||
pull request when the mesh built a module from that repository into that branch, and ran the
|
||||
repository's `merge-check.sh`, or the gate alone. A repository nothing is built from (the decision
|
||||
records, the lab) was not checked at all, and its pull request kept the forge's *pending* forever. A
|
||||
repository with no script ran only the gate, and nobody was told its own tests never ran.
|
||||
- **The gate had its own idea of what a change touches.** The merge handler, the release planner's
|
||||
what-if, the gate's *rebuild width* and the gate's composition each read a change's files in their own
|
||||
way. Two of them agreed with each other; none of them was guaranteed to agree with the plan a merge
|
||||
then made.
|
||||
- **The rule they shared was wrong.** A file in no module's directory was read as *shared code*, and
|
||||
everything built from the repository was rebuilt for it. The builder never reads such a file: it clones
|
||||
the repository and builds within the module's own directory (the whole repository for a module built
|
||||
from its root), plus any other repository an artifact's recipe names. Adding `merge-check.sh` at the
|
||||
catalogue's root planned 103 rebuilds ([issue 280](../04-ISSUES/280-a-rebuild-of-an-unchanged-source-was-read-as-a-new-bus/00-report.md),
|
||||
*Left open*). [Issue 278](../04-ISSUES/278-a-module-held-by-no-machine-was-read-as-shared-code/00-report.md)
|
||||
and [issue 252](../04-ISSUES/252-a-merges-changed-modules-were-read-wrong/00-report.md) had each patched
|
||||
an exception into the same rule.
|
||||
- **Nothing stopped a commit off the trunk becoming a module's version.** `build --ref <branch>` of a
|
||||
feature branch registered what it built, and the next push could send it. A pull request's head was
|
||||
only kept out of the catalogue by the check never asking to register it — a convention.
|
||||
|
||||
## Considered Options
|
||||
|
||||
**What decides whether a pull request is checked.**
|
||||
|
||||
1. *The repository opts in*, with a script or a registration. Rejected: a repository that has not opted in
|
||||
is exactly the one nobody is watching, and the forge said *pending* for it forever.
|
||||
2. **The mesh's module graph** — chosen. The controller holds every module, the repository and directory
|
||||
it is built from, and the build records' other repositories. Every pull request the forge holds is
|
||||
announced, and the graph says what it reaches.
|
||||
|
||||
**Where what a change touches is computed.**
|
||||
|
||||
1. *In the gate, beside the planner.* Rejected: two computations of one fact drift, and the drift is found
|
||||
when a merge does something its check did not say.
|
||||
2. **In the planner, once** — chosen. One function maps a changed file onto modules, one function answers
|
||||
what a merge would move and build; the merge handler, the what-if, the gate and the check all ask them.
|
||||
|
||||
**What a file outside every module's directory touches.**
|
||||
|
||||
1. *Everything built from the repository* (the shared-code rule). Rejected: no build reads it — the cost
|
||||
was 103 rebuilds for a script at the root.
|
||||
2. **Nothing** — chosen. A build reads its module's directory and the repositories its recipes name;
|
||||
a repository a recipe names is the build record's, already followed.
|
||||
|
||||
**How a commit off the trunk is kept from being published.**
|
||||
|
||||
1. *By convention*: checks do not ask to register. Rejected: a person building a branch by hand registered
|
||||
it, and a definition nobody had reviewed reached a machine ([issue 240](../04-ISSUES/240-a-dry-run-build-is-recorded-and-rolled-out/00-report.md)'s class).
|
||||
2. **By refusal in code**: the build seat says which branches hold the commit it built; the controller
|
||||
records and never registers a build off its module's trunk — chosen.
|
||||
|
||||
## Decision
|
||||
|
||||
1. **The commit is the build at hand, and where it sits decides what may happen.** A commit **not on the
|
||||
trunk** — a pull request's head, any branch — is only *checked*: its change plan computed, the gate run
|
||||
(composed machines validated, replays), its own tests run, the verdict posted. Nothing of it is
|
||||
registered or sent to any machine; anything built to check it is never registrable. A commit **on the
|
||||
trunk** is *published* — its builds registered as the module's version — and *pushed*, by the gated
|
||||
release. **The trunk** is the branch the module follows; for a module new to the catalogue, its
|
||||
repository's default branch as the forge names it. Enforced in code: the build seat reads, from its own
|
||||
fresh clone, the default branch and every branch holding the commit, and says them with the outcome;
|
||||
the controller records a build off its module's trunk and refuses to register it, naming the trunk —
|
||||
which covers `build --ref`, `rebuild` and `replay --register` alike. A check's or a dry run's outcome
|
||||
is never registered. A build seat older than this rule says nothing, and its build is registered as
|
||||
before and said, so the rule can reach the mesh through the build seat it is built into.
|
||||
2. **One commit, one change plan.** A change plan is computed from a diffset — a repository, the branch it
|
||||
merges into, the commit at hand — by the planner: the **build plan** (the modules the merge moves
|
||||
itself, their dependents in tiers; whether each is a move is its build's source fingerprint, issue
|
||||
280), the **deploy plan** (per machine, what it is sent in the build plan's order; what waits there
|
||||
for a person; steps that are not an ordinary send flagged: a planned bus step, a provider whose
|
||||
consumers are sent again, a module keeping data per ADR 0232/0233), and the **verdict** (the composed
|
||||
machines, the replays). It is one object: a pull request's check posts it as its result, the release
|
||||
after the merge follows the same planner and says what differs when another merge landed meanwhile,
|
||||
and `plans` answers it for any base and head. It is kept — its id, its inputs, its result — so the
|
||||
pull request, the release and the operator refer to the same thing.
|
||||
3. **The planner maps a change onto the modules, once.** A changed file touches exactly the modules whose
|
||||
build reads it: a module's own directory, the whole repository for a module built from its root, and
|
||||
a repository a recipe names (the build record's `read`). A file read by no build — at the root, in a
|
||||
directory no module is in — touches nothing and is said as such. A directory the change adds a
|
||||
`module.json` in, which the graph does not hold, is a new module: checked, never built by the merge.
|
||||
One function does the mapping and one answers the whole reach; the merge handler, the release
|
||||
planner's what-if, the merge gate and a pull request's check call them, and nothing else maps a path.
|
||||
4. **The graph decides what is checked, in two layers** (replacing ADR 0237 decision 4's *for a
|
||||
repository it builds a module from into that branch* and *or the gate alone*). The forge's holder
|
||||
announces every pull request it holds, with the directories holding a module at its head, the files
|
||||
it deletes and whether its head has a `merge-check.sh`. The controller answers every one:
|
||||
- a change that reaches a module, or adds one: the build seat runs **the gate**, status
|
||||
`mesh/merge-gate` — the touched manifests through `module check` (a problem the base branch already
|
||||
had is said and fails nothing), every machine composed with the definitions of the modules the plan
|
||||
moves or adds (not every definition in the tree), the replays — judged by the controller the mesh
|
||||
runs, a controller change by itself, a node-engine change by the running controller with its
|
||||
validator;
|
||||
- every repository of the mesh — one a module is built from on some branch, one of the core's owner,
|
||||
one the change adds a module to — gets **its own check**, status `mesh/repo-check`: its
|
||||
`merge-check.sh`, in the toolchain it declares (`# mesh-check-toolchain: go|typescript`); a
|
||||
repository with none is a **warning**, never a pass and never silent;
|
||||
- a change that reaches nothing is a pass that says so — a fact, not a missing check — and a
|
||||
repository outside the mesh is told nothing more.
|
||||
5. **Required statuses are the operator's setting, applied by the forge's holder.** `mesh/merge-gate` is
|
||||
required on the trunk of every repository a module is built from, the list derived from the graph;
|
||||
`mesh/repo-check` as well on the core repositories. The forge module's
|
||||
`gitea_branch_protection_get` / `gitea_branch_protection_set` read and set it; a new rule refuses direct
|
||||
pushes.
|
||||
6. **A change plan is a state machine, one table.** States and the transitions allowed between them,
|
||||
each with its guard, compiled once; any other transition is refused. `proposed` (a head) → `checked`
|
||||
→ `rejected` | `ready`; `ready` → `published` (guard: the commit on the trunk, its builds registered)
|
||||
→ `releasing` (per machine: sent → judging → passed | failed → rolled-back) → `done` | `failed` |
|
||||
`superseded` (a newer plan for the same repository and trunk) | `stopped` (a person, with why) |
|
||||
`held` (waits for a person: the release backlog, a bus step, a module whose policy records) →
|
||||
`releasing` (guard: a person's decision, with why). It replaces the release plans' implicit states
|
||||
(open, building, judging, done, failed, superseded, stopped, held), so there is one machine, not two.
|
||||
Every transition is kept with the plan and the commit, said on the bus, and appended to the commit's
|
||||
note; the plan resumes from its recorded state under the lease after a restart; a state held past its
|
||||
bound raises a condition, and healer H2 works from the table.
|
||||
7. **The plan is attached to its commit.** The `mesh/merge-gate` status links to the kept plan and
|
||||
describes it in a line ("builds gitea → the control node; no bus step; 4/4 compose"). A git note under
|
||||
`refs/notes/mesh-plan` on the pull request's head carries the plan's id and the predicted summary; on
|
||||
the merge commit on the trunk, the executed plan — what was built, sent where, the gates' verdicts,
|
||||
rollbacks, timings — written by the mesh's own forge account after the release, never by a person's
|
||||
or an agent's hand. The note writer appends: running twice adds nothing, and an outcome amends the note,
|
||||
never history. `git log --notes=mesh-plan` shows each commit's plan.
|
||||
|
||||
## Consequences
|
||||
|
||||
- **A module built from a branch other than its repository's default keeps that branch as its trunk.**
|
||||
Three applications are built from such a branch; a module new to the catalogue from one is refused until
|
||||
the branch is the default or merged into it.
|
||||
- **The build seat must be updated before the trunk rule bites.** Until the build seat built from this
|
||||
change is held, it says nothing and its builds register as before, said in the controller's log.
|
||||
- **The repository's own check runs code nobody has approved, and is given nothing to leak**: no container
|
||||
runtime socket, no package-registry credential. A suite that needs the mesh's own packages from the
|
||||
registry says those tests did not run; the Go toolchain gains a C compiler (the race detector) and Python
|
||||
(the decision records' checks), and the TypeScript toolchain git.
|
||||
- **A rebuild is narrower**: a file at a repository's root rebuilds nothing; the release planner and the
|
||||
gate say the files no build reads.
|
||||
- **What is decided here and not yet built** is listed in to-be 45's Phase 5 and stays there until it is:
|
||||
the kept change plan and its comparison at release, the state machine replacing the release plans'
|
||||
states, the notes, the status's link.
|
||||
|
||||
## How it is checked
|
||||
|
||||
| Rule | Checked by |
|
||||
|---|---|
|
||||
| a commit off its module's trunk is recorded and never registered; a check or a dry run never is | the controller's test of the publish rule (on the trunk, off it, a module following another branch, a feature branch named by hand, a check, a dry run, a build seat that says nothing); the builder's test reading the trunk and the branches holding a commit from a fresh clone |
|
||||
| one function maps a changed file onto modules, and every reader asks the planner | the controller's tests that a pull request's reach is the merge's (moved, dependents, width, unread) for a root file, a module's directory and both; the merge handler's and the gate's width tests on the same rule; a review of the callers, listed in the pull request |
|
||||
| a file no build reads touches nothing; a repository a recipe names reaches its packager | the merge-handler tests (a root file, a directory with no manifest, a file among the modules), the gate's width test (a root file and a README rebuild nothing), the check's test of a packaged repository |
|
||||
| every pull request is answered: a gate when it reaches a module, a repository check for the mesh's repositories (a warning without a script), a pass that says so otherwise | the controller's scope tests; the builder's test of a check with nothing to run; the builder's live tests (a script run beside the mesh's versions, failing, in a toolchain the mesh does not hold, past its bound, the gate with a stand-in judge) |
|
||||
| a manifest problem the base already had fails nothing | the builder's live gate test with a manifest broken on the base branch |
|
||||
| the statuses and the plan reach the pull request; an error is never a success | the forge module's tests of both statuses, the plan's line and comment |
|
||||
| the change plan says what each machine receives and what is not an ordinary send | the controller's change-plan test (a module's own change, the bus with its dependents and a module that waits, a root file) |
|
||||
| a branch protection rule is set as asked and a new one refuses pushes | the forge module's protection tests |
|
||||
| the state machine refuses a transition not in its table; notes are append-only | not yet built: a test walking the table, as the signals and healers tables are walked; the note writer's idempotence test |
|
||||
|
||||
## References
|
||||
|
||||
- [ADR 0237](0237-a-change-is-judged-against-the-mesh-that-runs-before-it-merges-on-the-build-seat.md),
|
||||
[ADR 0236](0236-a-build-is-judged-on-its-first-machine-and-put-back-by-something-other-than-itself-and-so-it-rolls-out-unattended.md),
|
||||
[ADR 0162](0162-a-merge-produces-a-tiered-plan-the-mesh-keeps.md),
|
||||
[ADR 0132](0132-a-seat-carries-the-tools-its-holder-must-serve.md).
|
||||
- [to-be 45](../03-DESIGN/01-to-be/45-a-core-that-cannot-fail-silently.md) §9 and Phase 5;
|
||||
[to-be 30](../03-DESIGN/01-to-be/30-the-mesh-updates-itself-on-a-push.md).
|
||||
- Issues [252](../04-ISSUES/252-a-merges-changed-modules-were-read-wrong/00-report.md),
|
||||
[278](../04-ISSUES/278-a-module-held-by-no-machine-was-read-as-shared-code/00-report.md),
|
||||
[280](../04-ISSUES/280-a-rebuild-of-an-unchanged-source-was-read-as-a-new-bus/00-report.md).
|
||||
- mesh-controller #101, mesh-catalog #98, mesh-host #43, mesh-tools #18, mesh-tools-go #1, mesh-sdk #11,
|
||||
mesh-lab #53, mesh-media-catalog #12, and the applications' own checks.
|
||||
@@ -206,6 +206,7 @@ python3 00-META/checks/index.py fail if stale
|
||||
- **0234** — [The mesh holds a conversation with its operator, over channels that are seats, and an answer that performs an action is authorised by the controller](0234-the-mesh-holds-a-conversation-with-its-operator.md)
|
||||
- **0236** — [A build is judged on its first machine and put back by something other than itself, and so it rolls out unattended](0236-a-build-is-judged-on-its-first-machine-and-put-back-by-something-other-than-itself-and-so-it-rolls-out-unattended.md)
|
||||
- **0237** — [A change is judged against the mesh that runs, before it merges, on the build seat](0237-a-change-is-judged-against-the-mesh-that-runs-before-it-merges-on-the-build-seat.md)
|
||||
- **0238** — [A commit is the build at hand: one commit, one change plan, checked off the trunk and published only on it](0238-a-commit-is-the-build-at-hand-one-commit-one-change-plan-checked-off-the-trunk-and-published-only-on-it.md)
|
||||
|
||||
### Its tiers, from the bottom up
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ status: proposed
|
||||
code: []
|
||||
updated: 2026-10-06
|
||||
decisions:
|
||||
- 02-DECISIONS/0238-a-commit-is-the-build-at-hand-one-commit-one-change-plan-checked-off-the-trunk-and-published-only-on-it.md
|
||||
- 02-DECISIONS/0221-a-push-sends-no-build-a-policy-or-a-plan-holds-back-except-to-the-machine-it-names.md
|
||||
- 02-DECISIONS/0218-a-plan-sends-grants-before-code-rolls-out-one-machine-first-and-a-newer-merge-takes-over-an-older-plan.md
|
||||
- 02-DECISIONS/0162-a-merge-produces-a-tiered-plan-the-mesh-keeps.md
|
||||
@@ -159,6 +160,15 @@ code. From an announcer that does not list them, the rule above stands. A change
|
||||
rebuilds the build agent alone: what it builds is ordered after it in a plan, never added to one for its
|
||||
sake.
|
||||
|
||||
Revision, [ADR 0238](../../02-DECISIONS/0238-a-commit-is-the-build-at-hand-one-commit-one-change-plan-checked-off-the-trunk-and-published-only-on-it.md)
|
||||
(2026-10-06), closing [issue 280](../../04-ISSUES/280-a-rebuild-of-an-unchanged-source-was-read-as-a-new-bus/00-report.md)'s
|
||||
*left open*. **There is no shared code.** A changed file touches exactly the modules whose build reads
|
||||
it — the module's own directory, the whole repository for a module built from its root, a repository a
|
||||
recipe names — and a file no build reads, at the root or in a directory holding no module, rebuilds
|
||||
nothing. One function maps a changed file onto modules and one answers what a merge moves and builds;
|
||||
the merge handler, the what-if, the merge gate and a pull request's check ask them. Only a commit on the
|
||||
module's trunk is registered.
|
||||
|
||||
## What a push does not send (2026-10-05)
|
||||
|
||||
Revision, [ADR 0221](../../02-DECISIONS/0221-a-push-sends-no-build-a-policy-or-a-plan-holds-back-except-to-the-machine-it-names.md).
|
||||
|
||||
@@ -4,6 +4,7 @@ status: in-progress
|
||||
code: [mesh-controller, mesh-host, mesh-tools, mesh-catalog, mesh-sdk, mesh-lab]
|
||||
updated: 2026-10-06
|
||||
decisions:
|
||||
- 02-DECISIONS/0238-a-commit-is-the-build-at-hand-one-commit-one-change-plan-checked-off-the-trunk-and-published-only-on-it.md
|
||||
- 02-DECISIONS/0237-a-change-is-judged-against-the-mesh-that-runs-before-it-merges-on-the-build-seat.md
|
||||
- 02-DECISIONS/0236-a-build-is-judged-on-its-first-machine-and-put-back-by-something-other-than-itself-and-so-it-rolls-out-unattended.md
|
||||
- 02-DECISIONS/0234-the-mesh-holds-a-conversation-with-its-operator.md
|
||||
@@ -512,6 +513,22 @@ makes any machine fail to compose or validate fails its check, naming the machin
|
||||
module. The resolver module's tests run under both C libraries the snapshot lists. A test in each core
|
||||
repository asserts that a pinned dependency's version equals the version the snapshot says runs.
|
||||
|
||||
Revision, [ADR 0238](../../02-DECISIONS/0238-a-commit-is-the-build-at-hand-one-commit-one-change-plan-checked-off-the-trunk-and-published-only-on-it.md)
|
||||
(2026-10-06). **The commit is the build at hand.** A commit off its module's trunk is only checked; a
|
||||
commit on it is published and pushed, and the controller refuses to register a build of one off it. **The
|
||||
module graph, not the repository, decides what a pull request's check runs**: every pull request the
|
||||
forge holds is announced, and the controller asks the planner — the one function that maps a changed file
|
||||
onto modules, and the one answer of what a merge moves and builds — what a merge of the head would reach.
|
||||
A changed file touches exactly the modules whose build reads it; a file no build reads touches nothing. A
|
||||
change reaching a module, or adding one, runs **the gate** on the build seat (`mesh/merge-gate`): the
|
||||
touched manifests through `module check`, failing only what the change brings; every machine composed with
|
||||
the definitions of the modules the plan moves or adds; the replays. Every repository of the mesh runs **its
|
||||
own** `merge-check.sh` (`mesh/repo-check`) in the toolchain it declares, a warning when it has none. The
|
||||
check's result is the commit's **change plan** — the build plan, the deploy plan machine by machine with
|
||||
what is not an ordinary send, and the verdict — posted on the pull request. The plan is one object with
|
||||
a state machine, kept, followed by the release and written to the commit as a note; which parts are built
|
||||
is Phase 5's.
|
||||
|
||||
**The replays.** mesh-lab carries a scripted scenario for each core incident, asserting the rule's
|
||||
outcome, run on every merge to mesh-controller, mesh-host and mesh-tools:
|
||||
|
||||
@@ -702,6 +719,24 @@ rest of the window's incidents as replays; the merge gate's first runs against t
|
||||
the status required to merge, which is the operator's setting on the forge; mesh-tools' and mesh-sdk's
|
||||
`merge-check.sh`.
|
||||
|
||||
**Revised 2026-10-06** ([ADR 0238](../../02-DECISIONS/0238-a-commit-is-the-build-at-hand-one-commit-one-change-plan-checked-off-the-trunk-and-published-only-on-it.md),
|
||||
the operator's "enable the checks on every repository of the mesh", "the logic acts on our module graph"
|
||||
and "the commit is the build at hand"), on branches, not yet merged:
|
||||
|
||||
| Repository | Delivers |
|
||||
|---|---|
|
||||
| mesh-controller | the planner's one mapping of a changed file onto modules and its one answer of a merge's reach, asked by the merge handler, the what-if, the gate and the check; a file no build reads touches nothing (issue 280's *left open*); every pull request answered — the gate when it reaches a module, the repository's own check for the mesh's repositories, a pass that says so otherwise; the gate run by the build seat with its judge chosen from the graph, composing the plan's definitions only, failing only a manifest problem the change brings; the change plan computed and carried with the verdict; a build of a commit off its module's trunk recorded and never registered; its own manifest naming every verb of its seat |
|
||||
| mesh-catalog | the forge's announcer saying, with every pull request, the directories holding a module at its head, the files it deletes and whether it has a `merge-check.sh`; both statuses and the change plan on the pull request; `gitea_branch_protection_get` and `gitea_branch_protection_set`; the catalogue's own check |
|
||||
| mesh-host, mesh-tools, mesh-sdk, mesh-lab, mesh-media-catalog, and the applications built from their own repositories | each its own `merge-check.sh`; mesh-tools' tests each on a bus of their own |
|
||||
| mesh-tools-go, mesh-tools | a C compiler and Python in the Go toolchain, git in the TypeScript one |
|
||||
| hq | its own `merge-check.sh`, running `records.py`, `index.py` and `cycle.py` |
|
||||
|
||||
**Not yet:** the change plan kept (id, inputs, result) and the release comparing its plan with it; the
|
||||
state machine replacing the release plans' states, with its table, its test, its conditions and healer H2;
|
||||
the status's link to the kept plan; the notes under `refs/notes/mesh-plan`; check builds in a scratch
|
||||
namespace (the check builds no module today, so there is none to keep apart yet); the statuses made
|
||||
required — prepared as calls of the forge module's tool, applied by the operator.
|
||||
|
||||
## What is not decided here
|
||||
|
||||
- The bus as a cluster of three, to upgrade it live.
|
||||
|
||||
@@ -72,6 +72,11 @@ still treats such a file as shared code and rebuilds everything built from the r
|
||||
fix that costs build time and no longer moves anything. Narrowing it belongs to the controller's
|
||||
planning rule (issue 278's area) and is not done here.
|
||||
|
||||
> **Closed — 2026-10-06, by [ADR 0238](../../02-DECISIONS/0238-a-commit-is-the-build-at-hand-one-commit-one-change-plan-checked-off-the-trunk-and-published-only-on-it.md)**
|
||||
> (mesh-controller #101): a changed file touches exactly the modules whose build reads it, and a file at
|
||||
> the root rebuilds nothing — in the merge handler, the release planner, the merge gate and a pull
|
||||
> request's check, through one function.
|
||||
|
||||
## How it is checked
|
||||
|
||||
| Rule | Checked by |
|
||||
|
||||
@@ -47,7 +47,9 @@ vocabulary — *controller* (not "control plane"), *foundation* (not "substrate"
|
||||
|
||||
## Ground rules
|
||||
|
||||
- **Markdown only.** No new top-level folders without explicit confirmation.
|
||||
- **Markdown only** — but for the checks in `00-META/checks/` and `merge-check.sh` at the root, which
|
||||
runs them on every pull request as its `mesh/repo-check` ([ADR 0238](02-DECISIONS/0238-a-commit-is-the-build-at-hand-one-commit-one-change-plan-checked-off-the-trunk-and-published-only-on-it.md)).
|
||||
No new top-level folders without explicit confirmation.
|
||||
- **Status lives in YAML frontmatter** — on research overviews (`status`, `became`), design
|
||||
docs (`layer`, `status`, `code`, `updated`), issue reports (`status`, `located-in`,
|
||||
`fixed-by`, `amended-design`) and decision records (`status`, `date`, `deciders`).
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
# mesh-check-toolchain: go
|
||||
#
|
||||
# This repository's own check (ADR 0238): the second layer of a pull request's merge check,
|
||||
# `mesh/repo-check`, run by the build seat in the mesh's Go toolchain, which carries Python for it. No
|
||||
# module is built from here, so no gate runs (`mesh/merge-gate` says the change touches none). The three
|
||||
# checks every merge here must pass (AGENTS.md): the records' structure, the reading order, the cycle.
|
||||
set -eu
|
||||
python3 00-META/checks/records.py
|
||||
python3 00-META/checks/index.py
|
||||
python3 00-META/checks/cycle.py
|
||||
Reference in New Issue
Block a user