Compare commits

..
Author SHA1 Message Date
mesh-tools b29008ad36 Merge pull request 'Playbook 02: one design per thing' (#387) from process/02-one-design-per-thing into main 2026-10-16 17:41:22 +00:00
jschoubben 101d7f30f7 Playbook 02: one design per thing; a graduation rewrites the design that covers it instead of writing a second (the operator, 2026-10-16)
mesh/merge-gate head 101d7f30f7e2 merged into trunk 225eee14d0bf — pass: the change touches no module of the mesh's graph
mesh/repo-check head 101d7f30f7e2 merged into trunk 225eee14d0bf — pass: its merge-check.sh passed
mesh/delivery delivered
2026-10-16 19:40:48 +02:00
mesh-tools 225eee14d0 Merge pull request 'Design 47: a move of the trunk asks every active check again (ADR 0395)' (#381) from design/47-recheck-on-trunk-move into main 2026-10-16 17:35:52 +00:00
jschoubben 12e75cdfa2 Design 47: the transition paragraph, the recheck verb and the section's bullets say ADR 0395 whole (review)
mesh/merge-gate head 12e75cdfa215 merged into trunk f1081c4f9768 — pass: the change touches no module of the mesh's graph
mesh/repo-check head 12e75cdfa215 merged into trunk f1081c4f9768 — pass: its merge-check.sh passed
mesh/delivery delivered
2026-10-16 19:27:52 +02:00
jschoubben 377fa3f88a Design 47: say ADR 0395 as accepted — a conflict is asked again at every move, an ended check's builds are not reused, a group's composed check reruns through its members, and the cost bound 2026-10-16 19:26:47 +02:00
jschoubben 11e32ce5be Merge remote-tracking branch 'origin/main' into design/47-recheck-on-trunk-move 2026-10-16 19:26:35 +02:00
mesh-tools f1081c4f97 Merge pull request 'Playbook 08: a second fault the delivery shows joins the issue only in the same files' (#386) from fix/pb08-second-fault into main 2026-10-16 17:09:53 +00:00
mesh-tools 152cc0c0e7 Playbook 08: a second fault the delivery shows joins the issue only in the same files
mesh/merge-gate head 152cc0c0e77c merged into trunk a8b951f3b488 — pass: the change touches no module of the mesh's graph
mesh/repo-check head 152cc0c0e77c merged into trunk a8b951f3b488 — pass: its merge-check.sh passed
mesh/delivery delivered
Taken from issue 937, where mesh-catalog #335 was taken into the issue
and issue 943 was opened for a fault in other code.
2026-10-16 17:06:25 +00:00
mesh-tools a8b951f3b4 Merge pull request 'Playbook 08: needing a decision keeps a fix small' (#385) from process/08-a-decision-keeps-a-fix-small into main 2026-10-16 15:58:01 +00:00
jschoubben 0eadc27fc7 Playbook 08: needing a decision keeps a fix small; a feature is several modules with research or a design before it (the operator, 2026-10-16)
mesh/merge-gate head 0eadc27fc722 merged into trunk 4e437eb1488f — pass: the change touches no module of the mesh's graph
mesh/repo-check head 0eadc27fc722 merged into trunk 4e437eb1488f — pass: its merge-check.sh passed
mesh/delivery delivered
2026-10-16 17:46:23 +02:00
jschoubben 91f82cd38e Design 47: a group's own merge in order asks nothing again (ADR 0395 §1, review)
mesh/merge-gate out of date: judged against trunk b9af4e373dc0, the trunk is now 6dcfa2226e63; judged again on a recheck or when it is merged
mesh/repo-check out of date: judged against trunk b9af4e373dc0, the trunk is now 6dcfa2226e63; judged again on a recheck or when it is merged
mesh/delivery superseded: a newer head of the same pull request
2026-10-16 13:32:39 +02:00
jschoubben a65e1076a2 Design 47: a pull request that no longer merges cleanly is told, not checked (ADR 0395 §2)
mesh/merge-gate head a65e1076a2e5 merged into trunk b9af4e373dc0 — pass: the change touches no module of the mesh's graph
mesh/repo-check head a65e1076a2e5 merged into trunk b9af4e373dc0 — pass: its merge-check.sh passed
mesh/delivery superseded: a newer head of the same pull request
2026-10-16 11:42:03 +02:00
jschoubben 09ec150bd6 Design 47: a move of the trunk asks every active check again, one at a time per pull request (ADR 0395, issue 888)
mesh/delivery superseded: a newer head of the same pull request
mesh/merge-gate error: the check could not run: killed by hand
mesh/repo-check error: the check could not run: killed by hand
2026-10-16 11:40:14 +02:00
4 changed files with 50 additions and 19 deletions
+4 -1
View File
@@ -33,7 +33,10 @@ about an hour, and said to the operator if it runs past.
- **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:
3. **Write the design.** **One design per thing** (the operator, 2026-10-16): when a to-be design already
covers what the decisions change, they rewrite that design, as *Amending an existing design* below says,
and no second design is written beside it that refers to it. Only for something no design covers, create
the document under `03-DESIGN/01-to-be/` with frontmatter:
```yaml
---
+1 -10
View File
@@ -177,14 +177,6 @@ delivery: no machine receives it (issue 889 while it still starts one). The lead
naming its pull requests, and removes what is left: no `feat/<slug>` branch and no `.work/<slug>` worktree
survive.
**Removing what is left means everything the feature made, wherever it lives**: every worktree the lead or its
agents made (under `.work/<slug>`, in a session's scratchpad, a reviewer's copy), every per-issue or per-package
branch, and every branch the feature pushed to the forge. Before one goes, check it holds nothing that is not on
`main`. Compare content, not hashes: a commit put on the forge with `gitea_commit` lands with a new hash, so a
merged branch still shows commits "not on main" (`git diff origin/main <branch> -- <the files it changed>` is
empty when its content is there). What is not on `main` is delivered in the next step or written on its issue
before it goes. Feature 57 left over a hundred worktrees and per-issue branches in one scratchpad (2026-10-16).
## Models
| Who | Model | Why |
@@ -268,8 +260,7 @@ issues in `fixing` that nobody works on reads to the operator as stuck work.
request into a feature branch exists. A pull request per issue, or an agent waiting on a merge check in
phase 1, is the failure this playbook prevents.
- A context file exists per touched repository under `.work/<slug>/` while the feature runs.
- After a feature's delivery, `git branch -r | grep feat/<slug>` and `git worktree list` return nothing for it, in every clone the
feature used, its session scratchpads included.
- 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
+11 -5
View File
@@ -2,7 +2,10 @@
**Trigger.** One issue in one repository, small enough to build in about an hour: a bug with a known cause,
a missing check, a wording, a playbook or design edit. Anything larger, or anything that needs a change in a
second repository first, is a feature and follows [playbook 07](07-feature-branches.md).
second repository first, is a feature and follows [playbook 07](07-feature-branches.md). A feature is the
larger kind: it touches several modules and has a research effort or a design before it. **Needing a decision
does not make a fix a feature**: the decision is settled first (step 1) and the fix stays small (the operator,
2026-10-16).
**Related issues in one fix.** A small fix may cover two or three related issues when they are in the same
repository, mostly in the same module, and together still fit in about an hour: they touch the same files, or
@@ -23,7 +26,8 @@ one delivery**. Everything before the push is local and fast.
1. **Read the issue and the code it names** (the session's own model, or one read-only agent on the smaller
model answering exact questions with file:line). If a design question is open, it is settled before any
code is written: on the issue, through the knowledge base, or by the operator. A fix that turns out to
need a decision or a second repository stops here and becomes a feature.
need a second repository, or more than about an hour, stops here and becomes a feature; one that needs a
decision stays a small fix.
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
@@ -49,12 +53,15 @@ one delivery**. Everything before the push is local and fast.
or needs the operator's terminal.
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.
8. **Remove the fix's worktree and its branch**, local and on the forge, as playbook [07](07-feature-branches.md)
phase 4 says: content checked on `main` first, not hashes.
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.
**A second fault found by the delivery.** When a fix's delivery shows a second fault that keeps the issue's
done-when from holding, and that fault is in the same files, it is taken into the same issue as a second pull
request with a review round of its own. A fault in other code is opened as an issue of its own, and the first
issue waits for it (issue 937: mesh-catalog #335 was taken in; issue 943 was opened).
## Bounds
| Waiting on | Bound | Past the bound |
@@ -78,7 +85,6 @@ 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.
- After its delivery, no worktree and no branch named `fix/<issue>-…` is left, locally or on the forge.
- 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.
@@ -4,6 +4,7 @@ status: in-progress
code: [mesh-controller, mesh-catalog modules/mesh-delivery]
updated: 2026-10-16
decisions:
- "ADR 0395"
- "ADR 0382"
- "ADR 0350"
- "ADR 0335"
@@ -103,7 +104,9 @@ allows.
at the moment the build seat clones it, the **trunk commit**, and the verdict names both. When another merge
moves the trunk, a `ready` delivery goes back to `proposed` on the observed event `trunk moved`, with both
commits in the transition's reason; a `rejected` one stays `rejected`, its statuses saying the verdict is out
of date. Nothing is asked for it: a recheck, a new head or the merge tool asks the check again. The row from
of date. The move itself asks the check again of every active open pull request into that trunk that merges
cleanly (ADR 0395, *A move of the trunk asks every check again* below); a recheck, a new head or the merge tool
asks it too. The row from
`proposed` to `checked` takes only a verdict that names the trunk's head as its trunk commit, so a verdict for
an older trunk is kept and shown and does not count, and the rows reach a fixed point. Checked by
mesh-delivery's `TestATrunkMoveSendsAReadyDeliveryBackToProposed` and the table's own rollout.
@@ -124,7 +127,7 @@ What this leaves as it is, said so nobody reads more into it:
- **A check that was asked and never answers** is listed by `stalled` an hour after the ask, and is asked again
with `mesh-delivery.recheck`, which the merge tool's refusal names.
The transitions are those of ADR 0239 decision 2, ADR 0270 and ADR 0323. A delivery that is
The transitions are those of ADR 0239 decision 2, ADR 0270, ADR 0323 and ADR 0395. A delivery that is
merged while not `ready` goes to `held`. Its check did not pass, and only a person decides that it goes on. A
delivery merged with no rollout answering it within ten minutes is held too, with the true reason, and listed by
`stalled` at once. Nothing waits silently.
@@ -389,6 +392,34 @@ only once it is built.
A group's state is derived from its members and its composed check, and is shown, never stored apart from
them.
## A move of the trunk asks every check again
*ADR 0395, changing ADR 0323 §4.* When the forge's holder hears a repository's trunk move, mesh-delivery asks the
check of every active open pull request into that trunk against its new head at once, so a verdict is current by
the time anyone looks.
- **A conflict is told, not checked.** Before asking a check, mesh-delivery asks the forge whether the head merges
cleanly into the new head, which needs no builder. When it does not, no check is asked: its statuses fail naming the trunk commit and the files in
conflict where the forge gives them, and it is told once on the pull request, not again while the same conflict
stands. Every later trunk move and its next push ask the forge again; once it merges cleanly its check is asked.
- **One check per pull request.** When a check against a newer trunk commit is asked for a pull request, its check
against an older trunk commit is dropped if it waits and ended if it runs, said in the build log and on the
queue, as a new head already ends its old head's check (issue 726). An ended check delivers no verdict, so none of its builds is reused (ADR 0350 §7 keeps only builds a verdict
names); its scratch records wait for ADR 0350 §5's seven-day sweep. A try and a delivery's build are never touched.
- **The queue's order.** Delivery builds first; then checks of pull requests marked ready; then the rest, the most
recently pushed first.
- **Inactive pull requests are left out.** One with no push and no ready mark for 7 days is not asked again on a
trunk move; its statuses say out of date and that a push, a ready mark or a recheck asks its check. A recheck
takes a delivery that is still proposed and whose verdict is out of date, and asks its check (issue 888).
- **Groups.** For a group's members a move asks only each member's own check; the group's composed check runs again
through those rechecks (ADR 0323 §6) and is never asked by the move itself. A move made by a member merging in
the group's order asks the other members nothing, since they merge moments later; their verdicts are out of date
until then, and one that does not merge is asked again at the next move, its next push or a recheck.
**Its cost** is at most one check asked per active, cleanly merging pull request per trunk move: about 550 a day at
ADR 0323's measured load, fewer once conflicting and inactive ones are left out; ending an older check saves builder
time, not checks asked. Issue 944 measures it once built.
## What every transition does
In this order, each by its owner:
@@ -420,7 +451,7 @@ In this order, each by its owner:
| `what-if` | the delivery plan a diffset would have, asked of the controller's planner, kept nowhere |
| `table` | the state table and the machine-step table, with bounds and H2's repairs |
| `stalled` | every delivery held past its bound, with the transition H2 may take, and every waiting rollout no live delivery holds |
| `recheck` | a rejected or ready delivery back to proposed, with why |
| `recheck` | a rejected or ready delivery back to proposed, with why; a delivery still proposed whose verdict is out of date has its check asked (ADR 0395) |
| `release` | a held delivery to delivering, with why: a person's word |
| `stop` | any delivery not final to stopped, with why; its rollout is ended through the controller. On a rollout that carries other deliveries it first answers what ending the rollout would take down, and acts on `way`: `again` or `walk` (ADR 0299) |
| `close` | H2's only verb: the transition the table names for a stalled delivery, refused otherwise |