You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
ci_resolve_dirty binds merge.roadmap.driver to a path no .gitattributes selects — the id-keyed roadmap driver never runs on a real merge #3343
The id-keyed roadmap merge driver is bound but never selected, so every branch still conflicts on roadmap.yaml by line
Found while resolving #3297, which gh pr update-branch refused with "Cannot update PR branch due to conflicts".
scripts/lib/roadmap_merge.py is a 3-way merge driver that merges docs/roadmaps/roadmap.yamlby entry id. Re-running the exact merge through it produced 0 conflicts where plain git produced 2 conflict hunks / 6 markers. It works.
It just never runs.scripts/ci_resolve_dirty.sh::write_attrs_override writes only
docs/audits/*.jsonl merge=union
into its attributes override, and no .gitattributes anywhere declares docs/roadmaps/roadmap.yaml merge=roadmap — not on the PR base, not on the branch, not on origin/main. So the resolver binds merge.roadmap.driver to a path that no attribute ever selects, git falls back to the line-based merge, and the driver is dead code on every real merge.
Its self-test (ci_resolve_dirty.sh --selftest row 9) is green because the fixture writes that attribute line into a throwaway repo itself. A driver whose only exercise writes its own selector is the same anti-theater class as a gate that cannot fail — and a .gitattributes merge driver is retroactively inert anyway for branches cut before it lands, which is why the binding has to be per invocation.
Resolving #3297 required supplying the missing line by hand:
write_attrs_override emits the roadmap.yaml merge=roadmap line too.
A self-test row that does not write the attribute itself: run the resolver on a repo whose .gitattributes is exactly what the repo ships, and assert the driver engaged (e.g. by a conflict-free merge of two branches that both add an entry).
A row that proves the negative: with the attribute absent, the merge conflicts — so the row can tell "driver ran" from "git got lucky".
Mechanism, for the record: two PRs that both add a roadmap entry conflict by line even though the entries are independent, which is how PRs land in DIRTY and stay there.
triage 2026-09-23 (aprender-dd, standing triage owner): milestoned to 0.70.0, theme Fast Train (CI, gates, pv, release tooling, hygiene); it moved out of backlog (the 2026-09-17 overflow bucket, not a release).
Parked by APR-EPIC-001: over S3 budget (rank 142/142). Reopen = pull. Applied by aprender-d1: claude+agy both said close, apr shadow row recorded (handoff/close-quorum-2026-09-25.json).
Activity
noahgift commentedon Sep 23, 2026
triage 2026-09-23 (aprender-dd, standing triage owner): milestoned to 0.70.0, theme Fast Train (CI, gates, pv, release tooling, hygiene); it moved out of
backlog(the 2026-09-17 overflow bucket, not a release).noahgift commentedon Sep 25, 2026
Parked by APR-EPIC-001: over S3 budget (rank 142/142). Reopen = pull. Applied by aprender-d1: claude+agy both said close, apr shadow row recorded (handoff/close-quorum-2026-09-25.json).