Implement Tier 1.5 conflict resolution as a peer driver to merge_drive.py
that honours the same hard invariant: every commit on master came from a SHA
whose CI passed against the exact current master.
New components
- tools/conflict_drive.py: deterministic driver that picks PRs labelled
auto/needs-conflict-resolution, claims them via the shared
auto/claimed-merge label, attempts a deterministic rebase with
deepen-on-demand fallback, dispatches conflict-resolver-worker on
conflict, force-pushes with --force-with-lease, and clears the label
for merge_drive to re-pick. Includes 24h retry budget, escalation to
auto/needs-implementer, single-instance lock + heartbeat, opt-in
TOCTOU mitigations (CONFLICT_DRIVER_CYCLE_JITTER_SECONDS,
CONFLICT_DRIVER_VERIFY_CLAIM), startup TTL constraint and required-
labels assertions, and full SQLite telemetry.
- tools/_claim_runtime.py: shared HTTP/lock/heartbeat/claim primitives
extracted from merge_drive.py (driver-aware claim/release markers,
injectable op_label_map). merge_drive re-exports for back-compat.
- tools/_opencode_worker.py: blocking Python client for the OpenCode
HTTP API with O(N) string-aware bracket matcher for tolerant JSON
extraction from worker output.
- .opencode/agents/conflict-resolver-worker.md: subagent definition
with tight permissions and "always finish, never abort, never --skip"
doctrine.
- tools/inject_synthetic_conflict.py: CLI that creates PRs on a test
fork with guaranteed conflicts (trivial / multi-commit / unresolvable)
for end-to-end testing.
Telemetry & dashboard
- tools/_forgejo_cache.py: new conflict_drive_cycles table, cycle-level
escalated_count, indexed retry-budget query, mark_*_escalated helper.
- tools/render-pr-velocity.py + pr-velocity.canvas.template.tsx:
conflict-resolution activity section showing 7-day cycle counts,
resolved/escalated/timeout/push-rejected breakdowns.
Open-issue dependency check
- tools/merge_drive.py: pr_is_eligible now consults Forgejo's blocks
endpoint and applies auto/blocked-by-deps when any open dependency
exists. Read-only predicate _pr_has_open_dependencies; label
mutations live with the eligibility caller.
- tools/setup_auto_labels.py: provisions auto/blocked-by-deps.
Documentation
- docs/development/conflict-drive-plan.md: full plan including TOCTOU
race documentation (§3.3.1) with implementation/test pointers.
- AGENTS.md: operator-facing section on conflict_drive.py and the
expanded label registry.
Tests
- 300 unit tests pass / 1 skipped (opt-in fork integration test).
- Coverage includes JSON extractor fuzz, push-stderr classification,
PAT scrub, deepen-on-demand fallback, retry budget escalation,
cycle-level escalated_count stamping, claim collision detection
(latest-claim-only with marker-primary identity), jitter wiring,
and verify_claim_after_apply plumbing.
Quality invariant unchanged: conflict_drive.py only operates on PR head
branches, never on master. CI gating on the train-merge SHA continues
to enforce the exact-current-master rule for everything that lands.
Co-authored-by: Cursor <cursoragent@cursor.com>