Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ba7c9e7f17 |
@@ -364,9 +364,6 @@ planner, the rollout). **Downstream of** Module, Core, Health and repair and Dat
|
||||
- **delivery group** — two or more deliveries sharing a pull request head branch name across the mesh's
|
||||
repositories, delivered as one unit in an order declared (`after:`) or inferred by the planner. One
|
||||
level: a group holds deliveries, never groups. Its state is derived from its members, never set.
|
||||
- **release branch** — a branch other than `main`, shared by name across repositories, that collects a feature's
|
||||
merged work and is brought into `main` as one delivery (design 57's `feat/57-config-and-provisioning`). While it
|
||||
is in flight, a change that touches its files waits for it (playbook 07, *Is the coast clear?*).
|
||||
- **delivery plan** — what a delivery does to the mesh: its **build plan** (the modules it moves and
|
||||
their dependents, in tiers), its **deploy plan** (per node, what it receives and what waits for a
|
||||
person) and its verdict (the composed nodes, the replays). Computed by the controller's planner from a
|
||||
@@ -685,7 +682,6 @@ renaming one sense, the old sense moves to a *Not:* line and becomes mechanical.
|
||||
| release | a person letting a held delivery go on | **release** | Change and delivery |
|
||||
| | taking a consumer off a licence | **unbind** (verb `release`, to rename) | Identity and access |
|
||||
| | a copy of a work an engine can fetch | **media release** | Media |
|
||||
| | a branch brought into `main` as one delivery | **release branch** | Change and delivery |
|
||||
| gate | the judgement on a delivery's first node | **first-node gate** | Change and delivery |
|
||||
| | the pull request status | **merge gate** | Change and delivery |
|
||||
| | a failed step stopping its module's later steps (ADR 0136) | *a failed step holds its module* | Placement |
|
||||
|
||||
+1
-26
@@ -1,10 +1,9 @@
|
||||
---
|
||||
status: canonical
|
||||
updated: 2026-10-16
|
||||
updated: 2026-10-11
|
||||
derives: the constitution page
|
||||
decisions:
|
||||
- "ADR 0020"
|
||||
- "ADR 0391"
|
||||
---
|
||||
|
||||
# How we build
|
||||
@@ -173,30 +172,6 @@ quietly stop being true, and nobody will learn that from a document.
|
||||
Not test-driven development as a blanket rule — a test written first against undiscovered
|
||||
behaviour asserts a guess. The obligation is that every decision has a defender.
|
||||
|
||||
### Tests run at the lowest level that proves them, within a time budget
|
||||
|
||||
Three levels, by how much real system a test uses (ADR 0391):
|
||||
|
||||
| Level | Uses | Budget | Runs |
|
||||
|---|---|---|---|
|
||||
| **Unit** | one piece of logic alone: no database, network, bus, running service or other process | well under a second per test | locally, the tests of what changed, while working; and in the forge's checks |
|
||||
| **Integration** | the real thing beside it: a database, the bus, a catalogue tree | the repository's whole suite in seconds, never over sixty | only in the forge's checks, once per push |
|
||||
| **End to end** | the whole mesh, or a lab mesh, from the outside | — | only when the operator asks |
|
||||
|
||||
- **Test each behaviour at the lowest level that can prove it.** A defect found higher up gets a test at the
|
||||
lowest level that reproduces it, before its fix.
|
||||
- **A test that needs longer than a second, or a database, the network or a service, is not a unit test.**
|
||||
- **A suite over sixty seconds is a defect with its own issue**: it is made faster or split, not accepted.
|
||||
- **Never run a merge check, a throwaway database or an integration suite locally.** The forge's checks do,
|
||||
on the builder.
|
||||
- **A report names its tests and how long they took**, so a test over its budget is seen when it is added.
|
||||
|
||||
### Tests within a time budget — how it was earned
|
||||
|
||||
On 2026-10-16 a feature's fixing agents ran the catalogue's whole merge check (about ten minutes), a
|
||||
throwaway database and a locally built gate during local development. Each round cost tens of minutes and
|
||||
caught neither real failure; the forge's checks found both.
|
||||
|
||||
### A report is read from the system, never from what asked for it
|
||||
|
||||
The same rule as the two above, pointed at reporting rather than at verification. **Anything
|
||||
|
||||
@@ -30,15 +30,6 @@ An idea arrives in one of two forms, and the first step differs:
|
||||
2. **Ask the operator to set it up.** A few questions, one at a time, each answerable with a choice and
|
||||
carrying a recommendation: what comes first, what is out of scope, which options must be tried, what
|
||||
done looks like. Three to five questions is usual; the answers are the effort's first findings.
|
||||
- **Check every option against the mesh's own rules before offering it.** An option that breaks one
|
||||
(the core values in [`mission.md`](../mission.md), among them *the mesh owns the truth* and
|
||||
*sovereignty: external dependencies are deliberate and few*; the rules in
|
||||
[`how-we-build.md`](../how-we-build.md); and everything between modules over the bus, research 036) is
|
||||
dropped, or offered only with the rule it breaks named. A recommendation the operator has to argue back
|
||||
costs a version.
|
||||
- **Explain each question with a concrete picture** in the operator's words: what they would see, do or
|
||||
lose under each option. No internal names (a record number, a verb, a word the glossary lacks) without
|
||||
what it is beside it.
|
||||
3. **Take a number.** `knowledge-base.reserve` with `kind: research` and `for`: the effort's title. The number
|
||||
is spent whether or not the effort is ever proposed; one never proposed is withdrawn after a week. Never
|
||||
pick one by hand.
|
||||
@@ -57,25 +48,10 @@ An idea arrives in one of two forms, and the first step differs:
|
||||
lists them and gives the difference between two. Until issue 844 is delivered, the knowledge base
|
||||
takes a new version of an accepted, active effort only as a progressive insight: give `insight`, saying
|
||||
what the effort held before the new finding, and mark the finding in the text with its date.
|
||||
- **Propose a version per settled set, not per answer.** While the operator answers a run of questions,
|
||||
or while experiments run, keep the answers and findings in the session's save point and propose once
|
||||
when the set is settled. Each version is reviewed and resent whole, so a version per answer multiplies
|
||||
the reviews.
|
||||
- **Pre-check before proposing**, against what the review sends back most: every record, issue or design
|
||||
the text names is in `links`; work put off names the issue that tracks it (an acceptance test is not
|
||||
put-off work: it is what the build proves, step 6); each figure is given as measured (a range, not a
|
||||
rounded claim); no word on a glossary *Not:* line.
|
||||
- **Try at the cheapest level that answers the question.** A program's own behaviour (a library, a
|
||||
server, a protocol) is tried in process, on the machine's loopback, in minutes. Lab runs (about 12 to
|
||||
16 minutes fresh) are for the mesh's own code; before that code exists, a lab run tests nothing an
|
||||
in-process test does not, and its lab scenario is written as the build's acceptance test instead.
|
||||
6. **Settle the direction with the operator.** When the questions are answered, write `05-direction.md`:
|
||||
the proposed decisions in a few lines each, the options rejected and why, and the build's acceptance
|
||||
tests: what the build must prove before it is done, carried by its milestones (playbook
|
||||
[04](04-build-handoff.md)). Nothing else is left open: each question closes by a test, by a decision the
|
||||
effort records with its reason (a small design limit is the lead's), or by the operator. Ask the
|
||||
operator to confirm or change the direction, one point at a time, then propose it once. Then the effort
|
||||
graduates through playbook [02](02-graduation.md).
|
||||
the proposed decisions in a few lines each, the options rejected and why, what is left open. Ask the
|
||||
operator to confirm or change it, one point at a time. Then the effort graduates through playbook
|
||||
[02](02-graduation.md).
|
||||
|
||||
## Bounds and models
|
||||
|
||||
@@ -124,9 +100,6 @@ and why, is the more expensive half to rediscover.
|
||||
|
||||
The rules on an effort are the knowledge base's: `propose` refuses one that breaks a rule that judges one
|
||||
record (the module's table test holds one case per rule), and the rules that judge the whole record set run
|
||||
after every acceptance and raise a condition when one fails. The habits of steps 2, 5 and 6 (options checked
|
||||
against the rules, one version per settled set, the cheapest level, nothing left open) are the lead's, read by
|
||||
the reviewer; of the pre-check, `propose` refuses a link to nothing and a retired word, and the review returns
|
||||
a record named but not linked, an untracked deferral and a figure not as measured. That this repository holds
|
||||
no effort is `records.py`'s `no-records` check, on every pull request. An active effort with no new version
|
||||
for seven days is the smell of research left behind: its lead closes or continues it.
|
||||
after every acceptance and raise a condition when one fails. That this repository holds no effort is
|
||||
`records.py`'s `no-records` check, on every pull request. An active effort with no new version for seven
|
||||
days is the smell of research left behind: its lead closes or continues it.
|
||||
|
||||
@@ -23,16 +23,6 @@ about an hour, and said to the operator if it runs past.
|
||||
say which, in writing, before proceeding.
|
||||
2. **Record the decisions** (below, *Writing a decision record*): one record per choice that could be
|
||||
reversed on its own, not one record for the whole effort.
|
||||
- **Write them together, not one after another.** Reserve every number first, then propose each record
|
||||
as soon as it is written, without waiting for the review of the one before; the reviews run side by
|
||||
side, and the operator's asks for the records that need them arrive together. A record that
|
||||
`rests-on` or `extends` a sibling is proposed once that sibling is accepted.
|
||||
- **Take the clauses from the confirmed direction** and cite the effort (`cites`, `"research NNN"`) for
|
||||
the evidence instead of retyping its findings: a record's Context holds the few facts its decision
|
||||
rests on, with the effort named for the rest.
|
||||
- **Pre-check each record before proposing it**, as for research (playbook [01](01-research.md), step
|
||||
5): every record, issue or design it names is in `links`; each deferral names its issue; each figure
|
||||
is given as measured; no word on a glossary *Not:* line.
|
||||
3. **Write the design.** Create the document under `03-DESIGN/01-to-be/` with frontmatter:
|
||||
|
||||
```yaml
|
||||
@@ -46,8 +36,6 @@ about an hour, and said to the operator if it runs past.
|
||||
---
|
||||
```
|
||||
|
||||
The design lists the direction's acceptance tests: what the build proves before it is done.
|
||||
|
||||
4. **Hand it to the work breakdown.** The design goes on through playbook [04](04-build-handoff.md):
|
||||
milestones, issues, and each milestone built as one feature step (playbook [07](07-feature-branches.md)).
|
||||
5. **Close the effort.** `knowledge-base.propose` the effort again, whole, with `status: graduated` and a
|
||||
@@ -153,6 +141,4 @@ record (its module's table test holds one case per rule), and the four rules tha
|
||||
changes, an accepted record extending a superseded one) run after every acceptance and raise a condition
|
||||
when one fails. In this repository, `records.py` checks that a design's `decisions:` entries and every
|
||||
"ADR NNNN" in the text are well formed, and that no record is written here; `index.py` checks the reading
|
||||
order's six topics, which the knowledge base reads. The three habits of graduating step 2 (side by side, clauses
|
||||
from the direction, the pre-check) are the lead's, read by the reviewer; `propose` refuses a link to nothing,
|
||||
a deferral no issue tracks and a retired word, and the review returns a record named but not linked.
|
||||
order's six topics, which the knowledge base reads.
|
||||
|
||||
@@ -28,11 +28,10 @@ A design becomes **milestones**, and each milestone becomes **issues**:
|
||||
there; if it is not, write it before changing it. Building against an undocumented as-is is how a shipped
|
||||
behaviour gets lost.
|
||||
4. **Break it into milestones.** Write them into the design, in a section *Milestones*: for each, its number,
|
||||
its one-sentence outcome, the acceptance tests of the design it proves, the repositories it touches, and
|
||||
what it depends on. Order them so each is usable as soon as it is delivered, the smallest useful one
|
||||
first.
|
||||
5. **Ask the operator to confirm the milestones**, in a short table: number, outcome, the acceptance tests it
|
||||
proves, repositories, the parts each repository builds. Change what they change.
|
||||
its one-sentence outcome, the repositories it touches, and what it depends on. Order them so each is
|
||||
usable as soon as it is delivered, the smallest useful one first.
|
||||
5. **Ask the operator to confirm the milestones**, in a short table: number, outcome, repositories, the
|
||||
parts each repository builds. Change what they change.
|
||||
6. **Open the issues.** For each confirmed milestone, `issue-tracker.open` one issue per repository part, its
|
||||
title the symptom or capability in plain words, its report naming the design, the milestone and the
|
||||
decisions it builds with; link the order with `depends-on`. Write the issue numbers into the milestone's
|
||||
@@ -62,5 +61,5 @@ Read by the lead and the reviewer today; a check in hq's merge-check is tracked
|
||||
issues; an in-progress design without one is the smell of building without a breakdown.
|
||||
- Every issue a milestone names exists in the tracker (`issue-tracker.get`), and an issue in `fixing` names
|
||||
its milestone in its report.
|
||||
- A milestone whose issues are all `resolved` has had its delivery plan done; its outcome sentence and
|
||||
acceptance tests are proven on the mesh before the next milestone starts.
|
||||
- A milestone whose issues are all `resolved` has had its delivery plan done; its outcome sentence is proven on
|
||||
the mesh before the next milestone starts.
|
||||
|
||||
@@ -21,16 +21,6 @@ A small fix (one repository, one issue, about an hour of work) follows
|
||||
undelivered for a day: an issue done at 21:09 was still not on the machines at 15:00 the next day.
|
||||
- **Work that waits and nobody notices.** Most lost time was not work at all, but a check, a delivery plan
|
||||
or an agent waiting on something that had stopped, unseen.
|
||||
- **Review that keeps hardening.** One fix went through seven review rounds in five and a half hours, each
|
||||
asking for more hardening than its issue asked (issue 704, 2026-10-14). A round is for what makes the
|
||||
change wrong; everything else is an issue of its own.
|
||||
- **The first check after the whole branch is written.** A feature's catalogue branch, pushed once after
|
||||
hours of local work, met its first check on 2026-10-16 and failed on 29 problems, TypeScript errors among
|
||||
them, that a unit suite run continuously while working finds at once.
|
||||
- **A green pull request nobody marks.** An approved, green pull request that was not marked ready waited
|
||||
12 h 17 min for someone to merge it (mesh-catalog #300, 2026-10-14).
|
||||
- **A module proven only after it reached the machines.** The mail modules were delivered with unit tests
|
||||
only, then failed live three times (issues 859, 865, 868) and took five more hours of fixes.
|
||||
|
||||
## The shape
|
||||
|
||||
@@ -71,8 +61,7 @@ never into the running one, unless it blocks the running one.
|
||||
hold, and the patterns to copy (file:line);
|
||||
- what not to touch, and what lands beside it in other repositories;
|
||||
- the local facts: the worktree, the branch, the check commands, a temporary directory for tests outside
|
||||
the home (`TMPDIR`), and the unit tests to run (never a database server: tests that need one are
|
||||
integration tests, which the forge's checks run).
|
||||
the home (`TMPDIR`), a throwaway database server if the store tests need one.
|
||||
When the reading is large, a read-only agent on the smaller model answers the lead's exact questions with
|
||||
file:line, and the lead writes the file from its answers.
|
||||
5. **Move the issues to `fixing`**, `by` naming the feature's agent for that repository.
|
||||
@@ -83,8 +72,7 @@ never into the running one, unless it blocks the running one.
|
||||
issues one after another, committing each locally with a message naming the issue ("Keep the assignments
|
||||
on the bus (issue 652)"). It is not replaced per issue: the lead continues the same agent (by its id) with
|
||||
the next instruction, so its context is paid for once.
|
||||
- **Unit tests only, of what changed, each well under a second** (how-we-build §5, ADR 0391). Each issue's
|
||||
first test fails before its change and passes after; `gofmt`, `go vet`
|
||||
- **Unit tests only.** Each issue's first test fails before its change and passes after; `gofmt`, `go vet`
|
||||
and the repository's unit tests stay green. The integration tests (`merge-check.sh` with the store and the
|
||||
bus) wait for phase 3.
|
||||
- **Nothing is pushed** and no pull request is opened in this phase. Never land on a red check: run the
|
||||
@@ -114,40 +102,13 @@ never into the running one, unless it blocks the running one.
|
||||
It says which round it is in ("round 1 of at most 3").
|
||||
3. **The report goes to the same fixing agents** that wrote the code, continued by their ids, so they fix
|
||||
with the context they already hold. Each answers the reviewer: what it changed, per finding, or why not.
|
||||
4. **The reviewer reads the answers and the new commits**, and approves or reports again (step 5 says what a round
|
||||
may ask). After round 3 the lead stops and brings the operator what is left, with a recommendation.
|
||||
5. **A finding outside the issues' done-when is never a change asked, in any round.** More hardening, a
|
||||
further case, a nicer form: the reviewer opens it with `issue-tracker.open` and names the number in its
|
||||
report, and the round does not wait for it. What a round asks is only what makes the change wrong against
|
||||
its issues and its decisions.
|
||||
|
||||
## Is the coast clear?
|
||||
|
||||
Before the push of phase 3 (and of a small fix, playbook [08](08-small-fixes.md) step 5), the lead checks, for every
|
||||
repository the change touches, whether a **release branch** is in flight there: a branch other than `main` that
|
||||
collects a feature's merged work to bring it into `main` as one delivery.
|
||||
|
||||
1. **Look for one.** A pull request into `main` whose head is a release branch (`gitea.gitea_open_pulls`), a
|
||||
release branch holding merged work that `main` does not have yet (`git log origin/main..origin/<branch>`), or
|
||||
a delivery plan of that release branch still running (`mesh-controller.plans`).
|
||||
2. **Compare the files.** `git diff --name-only origin/main...origin/<release branch>` against the files the
|
||||
change touches.
|
||||
3. **Overlap: hold.** If the release branch touches a file the change touches, nothing is pushed into that repository
|
||||
until the release branch's delivery plan is done. Then the feature branch is brought up to the new `main`, the unit
|
||||
tests run again, and the push follows. The hold is on the wait list (its bound: the release branch's delivery plan),
|
||||
and is said to the operator with what the change waits for.
|
||||
4. **No overlap: go on.** A release branch in another repository, or one that shares no file with the change, does not
|
||||
hold it; its merge joins the merge window as any other (ADR 0276).
|
||||
|
||||
Merging beside a release branch still in flight would make its lead resolve someone else's conflicts in the
|
||||
middle of it, and could send part of the change with its delivery (2026-10-16: the file module's
|
||||
controller part touched four files feature 57's release branch also changed).
|
||||
4. **The reviewer reads the answers and the new commits**, and approves or reports again. From round 2 it
|
||||
asks changes only for a finding that makes the feature wrong; smaller points become issues of their own.
|
||||
After round 3 the lead stops and brings the operator what is left, with a recommendation.
|
||||
|
||||
## Phase 3 — Check (no review)
|
||||
|
||||
1. **Push every feature branch and open one pull request per repository, together, once the coast is clear**
|
||||
(above). The integration tests
|
||||
run only in the merge check (the operator, 2026-10-16), never before. Pull requests in two or
|
||||
1. **Push every feature branch and open one pull request per repository, together.** Pull requests in two or
|
||||
more repositories that share the branch name are one delivery group (ADR 0239 §2).
|
||||
Where a session pushes through the forge tool `gitea_commit` (one commit on the forge's current base), the
|
||||
reviewer first confirms that commit's tree equals the reviewed one.
|
||||
@@ -155,14 +116,8 @@ controller part touched four files feature 57's release branch also changed).
|
||||
second review: phase 2 reviewed this tree.
|
||||
3. **A check that fails** goes back to the reviewer with the failure, for **one more cycle** of phase 2 with
|
||||
the same fixing agents; then push once again.
|
||||
4. **The step's acceptance is proven before it is marked ready.** A step that adds or changes a module
|
||||
carries an integration test that starts the module whole, its process against the real bus and store, and
|
||||
shows the step's acceptance sentence; the forge's checks run it (ADR 0391 §1, §6). Unit tests alone are not
|
||||
that proof; the mesh has no end-to-end tests yet, and the lab is not used (the operator, 2026-10-16).
|
||||
5. **The reviewer marks each pull request ready as soon as the acceptance is shown** (`mesh/ready` and a
|
||||
comment `ready at <full sha>`, the head it approved); mesh-delivery merges it when its checks pass
|
||||
(ADR 0364). The operator's word is waited for only when the step changes what the operator sees, removes
|
||||
data, or needs a step only the operator's terminal can take; the lead says which before the step starts.
|
||||
4. **Mark each pull request ready** (`mesh/ready` and a comment `ready at <full sha>`) once the operator's word
|
||||
for the feature is given; mesh-delivery merges it when its checks pass (ADR 0364).
|
||||
|
||||
**One exception: a catalogue change that uses a new manifest word.** The catalogue's merge check reads
|
||||
manifests with the controller the mesh runs, so the controller's pull request is merged and delivered first;
|
||||
@@ -170,8 +125,7 @@ then `mesh-delivery.recheck` the catalogue's and merge it on the new verdict. Pl
|
||||
|
||||
## Phase 4 — Deliver
|
||||
|
||||
The merge starts the delivery plan: build, publish, send. A merge into a branch other than `main` is not a
|
||||
delivery: no machine receives it (issue 889 while it still starts one). The lead follows it to done
|
||||
The merge starts the delivery plan: build, publish, send. The lead follows it to done
|
||||
(`mesh-controller.plans` with `wait` and `until: done`), then resolves the feature's issues with `fixed-by`
|
||||
naming its pull requests, and removes what is left: no `feat/<slug>` branch and no `.work/<slug>` worktree
|
||||
survive.
|
||||
@@ -200,8 +154,6 @@ on, with when it started and its bound.
|
||||
| a fixing agent's issue | 30 minutes | ask it where it stands; split or take over |
|
||||
| the review | 15 minutes a round | ask the reviewer; stop at round 3 |
|
||||
| a merge check | 15 minutes | read the build queue (`mesh-controller.queue`) and the check's log |
|
||||
| the ready mark | 15 minutes after the acceptance is shown | the reviewer marks it, or the lead does |
|
||||
| a release branch in flight that shares files | its delivery plan done | report it every ten minutes; bring the branch up to `main` after |
|
||||
| a merge after ready | 5 minutes after the checks pass | read `mesh-delivery.show` for the delivery |
|
||||
| a delivery plan | its class's budget (`mesh-delivery.times`), at most 30 minutes | read `mesh-controller.plans`, then `mesh-delivery.stalled` |
|
||||
|
||||
@@ -246,13 +198,6 @@ lead prepares a `/clear` as the mesh's instruction "prepare before clear" says:
|
||||
feature's phase, its branches and heads, the context files' paths, the agents' ids, the wait list and the
|
||||
next action; then the prompt the operator pastes. The context files make the feature resumable after a clear.
|
||||
|
||||
## Issues that stop
|
||||
|
||||
An issue stays in `fixing` only while an agent works on it. A step that stops, for a wait past its bound, a
|
||||
hand-over, or the session's end, moves each of its issues not delivered back to `open` with
|
||||
`issue-tracker.move` and a note saying how far it got (its branch, its last commit, what is left). A list of
|
||||
issues in `fixing` that nobody works on reads to the operator as stuck work.
|
||||
|
||||
## How it is checked
|
||||
|
||||
- A feature's issues show their commits on the feature branch (`git log --grep 'issue <n>'`), and no pull
|
||||
@@ -262,14 +207,6 @@ issues in `fixing` that nobody works on reads to the operator as stuck work.
|
||||
- After a feature's delivery, `git branch -r | grep feat/<slug>` and `git worktree list` return nothing for it.
|
||||
- More than one open pull request in a repository that share no feature name, or a feature step whose issues
|
||||
stay in `fixing` for more than a working day, is the smell: stop and bring it to the operator.
|
||||
- A review report that asks a change outside the issues' done-when, or a fourth round, is the failure of the
|
||||
review rules; `issue-tracker.list` with `flag: abandoned` lists issues left in `fixing` with nobody on them.
|
||||
- A pull request reviewed and green but not marked ready for more than 15 minutes is a lead that did not
|
||||
mark it.
|
||||
- A pull request opened into a repository whose release branch was in flight and shared a file with it is the failure of
|
||||
*Is the coast clear?*; the lead's report names the check it made before the push.
|
||||
- A step that adds or changes a module marked ready with no integration test that starts the module whole is
|
||||
the failure of phase 3's fourth step.
|
||||
- A bed run from `.work/<slug>/mesh-lab` that fails naming a `.work/<slug>/<repo>/…` path it cannot find is a
|
||||
missing sibling worktree, not a mesh fault.
|
||||
|
||||
|
||||
@@ -26,39 +26,30 @@ one delivery**. Everything before the push is local and fast.
|
||||
need a decision or a second repository stops here and becomes a feature.
|
||||
2. **Move the issue to `fixing`** with `by` as who@node.
|
||||
3. **Build on a local branch** `fix/<issue>-<slug>`, in a worktree of its own branched from `main`. Write the
|
||||
test that fails today first; make the change; keep `gofmt`, `go vet` and the unit tests of what changed green
|
||||
(each well under a second; never a merge check or a database locally: how-we-build §5, ADR 0391).
|
||||
test that fails today first; make the change; keep `gofmt`, `go vet` and the repository's unit tests green.
|
||||
Commit, naming the issue. For a playbook or design edit, run the repository's own checks (in hq,
|
||||
`sh merge-check.sh`).
|
||||
4. **One review of the local commit, before anything is pushed** (a reviewer that did not write it, larger
|
||||
model; at most 3 rounds, as playbook 07; from round 2 only what is wrong; a finding outside the issue's
|
||||
done-when is opened as an issue of its own, never asked as a change). The reviewer's findings go back to the same agent that wrote the fix, continued by
|
||||
model; at most 3 rounds, as playbook 07; from round 2 only what is wrong). The reviewer's findings go back to the same agent that wrote the fix, continued by
|
||||
its id, so the fix keeps its context. A playbook or design edit of a few lines may skip the reviewer: the
|
||||
operator's word on the pull request is its review, and the lead marks it ready on that word.
|
||||
5. **Push once and open the pull request, once the coast is clear** (playbook [07](07-feature-branches.md), *Is
|
||||
the coast clear?*: no release branch in flight in the repository that shares a file with the fix). The forge's merge
|
||||
check runs the integration tests, the only
|
||||
place they run (the operator, 2026-10-16). A failed check
|
||||
operator's word on the pull request is its review.
|
||||
5. **Push the branch, try it, then open the pull request.** `mesh-controller.try` with the repository and the
|
||||
branch runs the merge check in the check's own toolchain before any status is set; open the pull request
|
||||
only once it passes. A local run never stands in for it: the check's containers carry other tools than the
|
||||
nodes (a test that called util-linux `flock -E` passed on a node and failed on BusyBox's in the check). The
|
||||
forge's merge checks run the integration tests. A failed check
|
||||
goes back to the same agent with the failure, and the reviewer reads only the change it makes.
|
||||
6. **The reviewer marks it ready at once** (for an edit that skipped the reviewer, the lead, on the
|
||||
operator's word) (`mesh/ready` and `ready at <full sha>`, the head it approved);
|
||||
mesh-delivery merges it when its checks pass. A fix to a module that changes how it runs carries an
|
||||
integration test starting the module whole against the real bus and store, run by the forge's checks
|
||||
(ADR 0391 §1, §6); unit tests alone are not that proof, and the lab is not used. The operator's word is waited for only when the fix changes what the operator sees, removes data,
|
||||
or needs the operator's terminal.
|
||||
6. **Mark it ready** (`mesh/ready` and `ready at <full sha>`) once the operator's word is given; mesh-delivery
|
||||
merges it when its checks pass.
|
||||
7. **Follow its delivery plan to done** (`mesh-controller.plans` with `wait` and `until: done`), prove the fix on
|
||||
the mesh (the symptom gone, measured), and resolve the issue with `located-in` and `fixed-by` the same hour.
|
||||
|
||||
A fix that stops before its delivery moves its issue back to `open` with a note saying how far it got
|
||||
(branch, last commit, what is left), as playbook [07](07-feature-branches.md) says.
|
||||
|
||||
## Bounds
|
||||
|
||||
| Waiting on | Bound | Past the bound |
|
||||
|---|---|---|
|
||||
| building the fix | 1 hour | it is a feature: stop and plan it under playbook 07 |
|
||||
| the review | 15 minutes | ask the reviewer where it stands |
|
||||
| the ready mark | 15 minutes after the review approved | the reviewer marks it, or the lead does |
|
||||
| the merge check | 15 minutes | read `mesh-controller.queue` and the check's log |
|
||||
| the merge after ready | 5 minutes after the checks pass | read `mesh-delivery.show` for the delivery |
|
||||
| the delivery plan | its class's budget (`mesh-delivery.times`), at most 30 minutes | read `mesh-controller.plans`, then `mesh-delivery.stalled` |
|
||||
@@ -75,8 +66,3 @@ reading itself and uses one subagent only for the review.
|
||||
- A small fix has one pull request with one or few commits naming its issue, opened after its review: a pull
|
||||
request with many heads is a fix reviewed after its push.
|
||||
- Its issue moves to `resolved` within the hour its delivery plan ends.
|
||||
- A pull request reviewed and green but unmarked
|
||||
for more than 15 minutes, a fix to a module's running marked ready with no integration test of the module whole, or a review report
|
||||
asking a change outside the issue's done-when, is the failure of steps 4 to 6.
|
||||
- An issue in `fixing` with nobody on it shows in `issue-tracker.list` with `flag: abandoned`; a stopped fix
|
||||
moves it back to `open` with its note.
|
||||
|
||||
@@ -2,9 +2,8 @@
|
||||
layer: to-be
|
||||
status: in-progress
|
||||
code: [mesh-controller, mesh-catalog modules/mesh-delivery]
|
||||
updated: 2026-10-16
|
||||
updated: 2026-10-13
|
||||
decisions:
|
||||
- "ADR 0382"
|
||||
- "ADR 0350"
|
||||
- "ADR 0335"
|
||||
- "ADR 0323"
|
||||
@@ -372,12 +371,6 @@ only once it is built.
|
||||
group's members puts the composed check out of date: the group reads `checking` with the reason, and the
|
||||
composed check runs again once a member is judged again. Checked by mesh-delivery's
|
||||
`TestAGroupsComposedCheckGoesOutOfDateOnAMergeThatIsNotItsMember` and `TestARebasedMemberIsComposedAgainNotHeld`.
|
||||
- **Each member's own check reads its siblings** (ADR 0382): the group's other open members into a base of
|
||||
the same name are read beside a member's own check at their head merged onto their base, and a mesh-controller
|
||||
sibling's merge judges it, so changes that are only consistent together pass their own checks. The controller
|
||||
learns the siblings from mesh-delivery's `groups`; the verdict names each one. A sibling's new head, close or
|
||||
base move puts that verdict out of date, and the merge tool merges such a member only when
|
||||
`mesh/delivery-group` passed at the heads read and every sibling head read is reviewed.
|
||||
- **Delivering**: in order. A member waits in `published` until the one before is `delivered` or `covered`.
|
||||
A member published while its group's composed check is asked and not answered waits there for the answer;
|
||||
one held because that check had not passed is *lifted* back to `published` once it passes or warns for the
|
||||
|
||||
Reference in New Issue
Block a user