decision: the per-unit TODO.md entry makes every merge invalidate every open PR #222

Open
opened 2026-08-11 14:54:59 +02:00 by clawbot · 1 comment
Collaborator

Your convention is that a unit's TODO.md update rides in the same commit as the work, and every unit adds a bullet at the top of # Completed Steps. With one PR in flight that is free. With a dozen it is quadratic: each merge conflicts every other open PR on that one list, and each conflict costs a dispatched rebase, a fresh make check, and a force-push.

Measured today: it is by far the largest single consumer of worker time in this milestone. #204 has now needed two rebases for nothing but this bullet — its substance passed review unchanged both times — and several other PRs have needed one each. The conflict is always the same trivial "keep both lines", and it is never interesting.

Nothing else about the convention is a problem. The entry itself is worth having; it is the placement — every unit writing to the same line of the same file — that serialises work that is otherwise independent.

Options

  • (a) Drop the per-unit TODO.md entry. The tracker is already authoritative for what landed, and each commit title ends (closes #N), so git log reconstructs the same history exactly. I would write the Completed Steps summary once per milestone, at close, from the closed-issue list.
  • (b) Keep the entry, append at the END of Completed Steps rather than the top. Reduces conflicts (git can often auto-merge appends to different offsets) without eliminating them, and inverts the list's newest-first order.
  • (c) Keep it exactly as is and accept the rebase cost.

Recommendation

(a). It removes the contention entirely rather than reducing it, loses no information, and the reconstruction at milestone close is more accurate than a dozen separately-authored bullets — those already vary in detail and phrasing depending on which worker wrote them. If you want the running log preserved between milestones, (b) is the cheaper compromise.

This is your convention and a workflow change, so it is your call. Nothing is blocked — I will keep dispatching rebases under (c) until you say otherwise.

Your convention is that a unit's `TODO.md` update rides in the same commit as the work, and every unit adds a bullet at the top of `# Completed Steps`. With one PR in flight that is free. With a dozen it is quadratic: each merge conflicts every other open PR on that one list, and each conflict costs a dispatched rebase, a fresh `make check`, and a force-push. Measured today: it is by far the largest single consumer of worker time in this milestone. https://git.eeqj.de/sneak/AutistMask/pulls/204 has now needed two rebases for nothing but this bullet — its substance passed review unchanged both times — and several other PRs have needed one each. The conflict is always the same trivial "keep both lines", and it is never interesting. Nothing else about the convention is a problem. The entry itself is worth having; it is the *placement* — every unit writing to the same line of the same file — that serialises work that is otherwise independent. ## Options - **(a) Drop the per-unit `TODO.md` entry.** The tracker is already authoritative for what landed, and each commit title ends ` (closes #N)`, so `git log` reconstructs the same history exactly. I would write the Completed Steps summary once per milestone, at close, from the closed-issue list. - **(b) Keep the entry, append at the END of Completed Steps** rather than the top. Reduces conflicts (git can often auto-merge appends to different offsets) without eliminating them, and inverts the list's newest-first order. - **(c) Keep it exactly as is** and accept the rebase cost. ## Recommendation **(a).** It removes the contention entirely rather than reducing it, loses no information, and the reconstruction at milestone close is more accurate than a dozen separately-authored bullets — those already vary in detail and phrasing depending on which worker wrote them. If you want the running log preserved between milestones, **(b)** is the cheaper compromise. This is your convention and a workflow change, so it is your call. Nothing is blocked — I will keep dispatching rebases under (c) until you say otherwise.
sneak was assigned by clawbot 2026-08-11 14:54:59 +02:00
Author
Collaborator

Measured again today at higher concurrency, since the number is now much worse than when this was filed.

Four units landed this session. At this moment three PRs are cleared on the merits by independent review and blocked on nothing but this bullet: #201, #248, #249. Every one has README.md auto-merging cleanly and TODO.md as the sole conflict.

Two things that were not visible when this was filed:

  1. It serialises the merge queue. Because each landing invalidates the rest, I cannot merge in parallel — it is rebase, merge, rebase, merge, one at a time, each with a full make check and e2e re-run. Concurrency in implementation does not buy concurrency in landing.
  2. A rebase is not always free. #248 had to be hand-resolved against real code conflicts in two view files, and the guards it collides with are themselves untested (#254), so a bad resolution would not have failed a test. The TODO.md collision is what forces the rebase; the risk arrives with it.

One further datum for option (b): the reviewer of #201 noted # Completed Steps is already no longer date-sorted, because "top of the list" and "newest" diverge once several units land in a day. So the ordering the current convention exists to preserve is not actually being preserved.

Recommendation unchanged: (a). I am still running (c) and will keep doing so until you say otherwise — nothing is blocked on this, it is just costing roughly one dispatched worker per landing.

Measured again today at higher concurrency, since the number is now much worse than when this was filed. Four units landed this session. At this moment **three PRs are cleared on the merits by independent review and blocked on nothing but this bullet**: https://git.eeqj.de/sneak/AutistMask/pulls/201, https://git.eeqj.de/sneak/AutistMask/pulls/248, https://git.eeqj.de/sneak/AutistMask/pulls/249. Every one has `README.md` auto-merging cleanly and `TODO.md` as the sole conflict. Two things that were not visible when this was filed: 1. **It serialises the merge queue.** Because each landing invalidates the rest, I cannot merge in parallel — it is rebase, merge, rebase, merge, one at a time, each with a full `make check` and e2e re-run. Concurrency in implementation does not buy concurrency in landing. 2. **A rebase is not always free.** https://git.eeqj.de/sneak/AutistMask/pulls/248 had to be hand-resolved against real code conflicts in two view files, and the guards it collides with are themselves untested (https://git.eeqj.de/sneak/AutistMask/issues/254), so a bad resolution would not have failed a test. The `TODO.md` collision is what forces the rebase; the risk arrives with it. One further datum for option (b): the reviewer of https://git.eeqj.de/sneak/AutistMask/pulls/201 noted `# Completed Steps` is already no longer date-sorted, because "top of the list" and "newest" diverge once several units land in a day. So the ordering the current convention exists to preserve is not actually being preserved. Recommendation unchanged: **(a)**. I am still running (c) and will keep doing so until you say otherwise — nothing is blocked on this, it is just costing roughly one dispatched worker per landing.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/AutistMask#222