every unit conflicts with every other unit in TODO.md, costing a rebase cycle per merge #300

Closed
opened 2026-08-17 08:53:48 +02:00 by clawbot · 1 comment
Collaborator

Structural, not urgent — filed so it is not rediscovered. Not blocking 1.0.0.

Observation

TODO.md requires each unit to insert a Completed Steps entry, and every unit inserts it at the same position: the head of # Completed Steps. Two branches cut from the same base therefore always conflict there, regardless of what code they touch.

Measured today across the 1.0.0 tail: with six units in flight, landing one unit invalidated every other open PR. #282, #286, #289 and #296 each needed a rebase whose ONLY conflict was this one, and #282 needed a second one after #291 landed. That is O(n²) rebase cycles in the number of concurrent units, and each cycle costs a full gate re-run because a clean textual merge can still break the build.

The resolution is always the same and always mechanical: keep both entries. That is the tell that the contention is positional, not semantic.

Why it is worth fixing rather than absorbing

It caps useful concurrency. The repo's own workflow says one branch and one PR per issue landing on next, which is the right shape, but the merge cost grows with the square of how many are open — so the policy that enables parallelism is throttled by a markdown ordering convention.

It also degrades the signal: a reviewer or worker who sees "conflict" learns nothing, because it is nearly always this. A real semantic conflict — #289's windowClosed collision with #284, which would have silently regressed a fix — is easy to wave through when every conflict before it was noise.

Options

  • (a) Append to the end of Completed Steps rather than the head. One-line convention change. Git still conflicts on adjacent appends, so this helps only slightly. Cheap, weak.
  • (b) Give Completed Steps a stable per-unit anchor — one file per unit under a TODO.d/ directory, or an entry keyed by issue number in sorted position. Distinct files never conflict; sorted-by-number entries conflict only on adjacent numbers. Costs a small tooling change to assemble the rendered TODO.md, and make fmt must cover it.
  • (c) Drop the "TODO.md updated in the same commit" requirement and record completion from the closed issue instead — the tracker is already authoritative, so the file partly duplicates it. Removes the contention entirely; loses the in-repo narrative for anyone reading the tree without the tracker.
  • (d) Leave it. Correct today, since the cost is only paid when many units are in flight, which is a pre-1.0 condition.

Recommendation

(c), after 1.0.0 ships. TODO.md's Completed Steps duplicates what closed issues already record, and the duplication is what creates the contention. If the in-repo narrative is worth keeping, (b) is the honest way to keep it.

Not (a) — it looks like a fix and mostly is not.

Deliberately not acting on this now: changing the commit convention mid-flight would invalidate the six in-flight branches a second time, which is the cost this issue exists to reduce.

Definition of done (once decided)

  • Concurrent units on distinct code paths no longer conflict in TODO.md, demonstrated by rebasing two same-base branches onto each other.
  • The repo workflow section at the top of TODO.md states the new convention.
  • make check passes.
Structural, not urgent — filed so it is not rediscovered. Not blocking 1.0.0. ## Observation `TODO.md` requires each unit to insert a Completed Steps entry, and every unit inserts it at the **same position**: the head of `# Completed Steps`. Two branches cut from the same base therefore always conflict there, regardless of what code they touch. Measured today across the 1.0.0 tail: with six units in flight, landing one unit invalidated every other open PR. https://git.eeqj.de/sneak/AutistMask/pulls/282, https://git.eeqj.de/sneak/AutistMask/pulls/286, https://git.eeqj.de/sneak/AutistMask/pulls/289 and https://git.eeqj.de/sneak/AutistMask/pulls/296 each needed a rebase whose ONLY conflict was this one, and https://git.eeqj.de/sneak/AutistMask/pulls/282 needed a second one after https://git.eeqj.de/sneak/AutistMask/pulls/291 landed. That is O(n²) rebase cycles in the number of concurrent units, and each cycle costs a full gate re-run because a clean textual merge can still break the build. The resolution is always the same and always mechanical: keep both entries. That is the tell that the contention is positional, not semantic. ## Why it is worth fixing rather than absorbing It caps useful concurrency. The repo's own workflow says one branch and one PR per issue landing on `next`, which is the right shape, but the merge cost grows with the square of how many are open — so the policy that enables parallelism is throttled by a markdown ordering convention. It also degrades the signal: a reviewer or worker who sees "conflict" learns nothing, because it is nearly always this. A real semantic conflict — https://git.eeqj.de/sneak/AutistMask/pulls/289's `windowClosed` collision with https://git.eeqj.de/sneak/AutistMask/pulls/284, which would have silently regressed a fix — is easy to wave through when every conflict before it was noise. ## Options - **(a) Append to the end of Completed Steps rather than the head.** One-line convention change. Git still conflicts on adjacent appends, so this helps only slightly. Cheap, weak. - **(b) Give Completed Steps a stable per-unit anchor** — one file per unit under a `TODO.d/` directory, or an entry keyed by issue number in sorted position. Distinct files never conflict; sorted-by-number entries conflict only on adjacent numbers. Costs a small tooling change to assemble the rendered `TODO.md`, and `make fmt` must cover it. - **(c) Drop the "TODO.md updated in the same commit" requirement** and record completion from the closed issue instead — the tracker is already authoritative, so the file partly duplicates it. Removes the contention entirely; loses the in-repo narrative for anyone reading the tree without the tracker. - **(d) Leave it.** Correct today, since the cost is only paid when many units are in flight, which is a pre-1.0 condition. ## Recommendation **(c), after 1.0.0 ships.** `TODO.md`'s Completed Steps duplicates what closed issues already record, and the duplication is what creates the contention. If the in-repo narrative is worth keeping, **(b)** is the honest way to keep it. Not **(a)** — it looks like a fix and mostly is not. Deliberately not acting on this now: changing the commit convention mid-flight would invalidate the six in-flight branches a second time, which is the cost this issue exists to reduce. ## Definition of done (once decided) - [ ] Concurrent units on distinct code paths no longer conflict in `TODO.md`, demonstrated by rebasing two same-base branches onto each other. - [ ] The repo workflow section at the top of `TODO.md` states the new convention. - [ ] `make check` passes.
Author
Collaborator

Duplicate of #222, which was filed 2026-08-11 and already carries two rounds of measurement and the same recommendation. Filed in error without checking the backlog first. Closing; no new comment added there, since the case has been made twice and is pending your call, not pending more evidence.

Duplicate of https://git.eeqj.de/sneak/AutistMask/issues/222, which was filed 2026-08-11 and already carries two rounds of measurement and the same recommendation. Filed in error without checking the backlog first. Closing; no new comment added there, since the case has been made twice and is pending your call, not pending more evidence.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/AutistMask#300