Development record
The `merge=union` driver that .gitattributes gives `.abcd/work/DECISIONS.md` and `CHANGELOG.md` (the remedy iss-118 adopted) holds for a local merge only; the forge does not apply it. A pull request's mergeability and the merge queue's merge are computed on the forge, so two open pull requests that each append a DECISIONS.md entry conflict there as soon as one merges, while a local `git merge` of the same two is clean. In autonomous run A every records pull request went DIRTY whenever another records pull request merged first (#678, #679 and #681 on 2026-09-23), and each was recovered by a local merge in the lane's worktree, a push to the same branch behind a ten-to-twenty-minute pre-push preflight, and a re-armed auto-merge. Nothing tells an author that the union driver stops at the local clone. Wanted: the .gitattributes comment and the conventions that cite the driver say it holds locally only, and the remedy that needs no driver (one file per decision, as iss-2609100507439414 and iss-2608220150157511 propose) is weighed with this cost counted, since it removes the conflict on the forge as well.
The merge=union driver that .gitattributes gives .abcd/work/DECISIONS.md and CHANGELOG.md (the remedy iss-118 adopted) holds for a local merge only; the forge does not apply it. A pull request's mergeability and the merge queue's merge are computed on the forge, so two open pull requests that each append a DECISIONS.md entry conflict there as soon as one merges, while a local git merge of the same two is clean. In autonomous run A every records pull request went DIRTY whenever another records pull request merged first (#678, #679 and #681 on 2026-09-23), and each was recovered by a local merge in the lane's worktree, a push to the same branch behind a ten-to-twenty-minute pre-push preflight, and a re-armed auto-merge. Nothing tells an author that the union driver stops at the local clone. Wanted: the .gitattributes comment and the conventions that cite the driver say it holds locally only, and the remedy that needs no driver (one file per decision, as iss-2609100507439414 and iss-2608220150157511 propose) is weighed with this cost counted, since it removes the conflict on the forge as well.
Grounds
- pursued: an author reading either convention learns the driver stops at the local clone; a convention citing merge=union as the remedy without that limit would show it wrong
Frontmatter
| id | iss-2609240646538011 |
|---|---|
| type | issue |
| lifecycle | resolved |
| severity | minor |
.abcd/work/issues/resolved/iss-2609240646538011-forge-ignores-merge-union-so-records-prs.md
open on GitHub ↗ · commit history ↗
mentions8
- adr-2610110925465593Decisions are one flat file each and the single log is retired
- dcn-26101610403840682026-10-16 — A drain lane merges the default branch first (facilitator-on-delegation, drain-many-accounts): the lane's sync step, which already merges landed sibling lanes and has the merge head validated, also merges origin's default branch whenever it has moved, before the records and the push, and is entered again from arming and from the merge wait when the open pull request starts to conflict; a conflict confined to declared generated files goes back to the implementer as a fix round under the host's permissions, with the validators judging the result, so abcd itself runs no command the repository declares; any other conflict hands the lane back naming the files (grounds: the forge ignores the merge drivers a local merge uses, iss-2609240646538011; iss-2610161015410527).
- dcn-26101707553034512026-10-17 — A lane's merge of the default branch is an issue run's, and re-enters its sync only over generated-file conflicts (facilitator-on-delegation, drain-many-accounts step 13): only an issue run's sync (a drain's lane, or a person's build of an issue) fetches origin's default branch and merges it whenever it moved, since an intent's run already syncs its own landed siblings and its other conflicts stay the sibling brief's; the generated-file conflict goes to the sync's fresh implementer, whose brief says to regenerate, and like every sync counts no fix round, a regeneration being no failed attempt; any other conflict is a final refusal naming the files, so the drain's stuck rule hands the lane back at once with nothing pushed; a pull request the forge reports conflicting at the arming or the merge wait re-enters the sync when a driver-free merge of the default branch and the pushed head, as the forge merges, conflicts in declared generated files alone or in none, withdrawing an armed merge first and keeping the records commit and the pull request, the push and arming made again after a fresh round; the drain's move takes that step itself for a parked lane, reads it as syncing and drives the lane again; the generated set is claim.GeneratedFiles, the matcher step 11 exports, with no second reader (grounds: GitHub's update branch and merge queues test a pull request merged with its base; the forge ignores local merge drivers, iss-2609240646538011; a stale forge verdict with nothing to merge stays a wait; iss-2610161015410527)
- iss-118DECISIONS.md and ACKNOWLEDGEMENTS.md are multi-writer single files, the merge-hotspot shape that one-writer-per-file rules out. DECISIONS.md was the only textual conflict of the two-programme merge (resolved by hand as a union of both sides). The remedy is a design call per the principle's bounds: per-decision records (full atomicisation, which needs a new id family plus an armed uniqueness detector) or a merge=union gitattribute (smallest fix, legitimate because the ledger's entries are anonymous dated lines that never need identity). ACKNOWLEDGEMENTS.md is the same shape at lower traffic.
- iss-2608220150157511Merge contention is structural in the shared registers, not the prose: append logs (.abcd/work/DECISIONS.md, 154 changes; the decomposition-calibration corpus, conflicted 2026-08-22) and the lint-gated indexes that index_drift forces every branch to co-edit (brief/06-delivery/03-out-of-scope.md drafts index, conflicted the same day; 04-surfaces/README.md; decisions/adrs/README.md; intents/README.md; release/surface.json). The fix shape for the indexes is already written down: the enumeration command in out-of-scope.md derives the list from the filesystem, so the committed copy could become generated-at-build and the lint compare against the derivation instead of a hand-edited region. Append logs tolerate union merges; the indexes do not
- iss-2609100507439414A managed repository's shared append-only files conflict on nearly every merge, and abcd propagates neither of the two remedies it has already adopted for itself.
- iss-2610280107422462Every records pull request that adds, plans or moves a draft intent rewrites the generated drafts index in .abcd/development/brief/06-delivery/03-out-of-scope.md, so two such pull requests open at once conflict as soon as the first merges: their insertions into the sorted one-per-line list land in neighbouring lines. On the night of 2026-10-27/28 it happened three times, #1131 against #1147, #1162, and lane E's rebase, and each was fixed by hand by merging the default branch, taking its side of the region and running go generate again. The forge applies no merge driver (iss-2609240646538011), and no verb regenerates the region when it files a record (iss-2610241256347199).
- itd-2610161016391855A stuck drain lane hands itself back