Public: anyone can read this; the crew can change it.

A merge conflict is not a failed try: the pull is brought up to date and its tries are kept #8022

Merged opened this in answer to

Check · Review · Land · Live done — Landed and live in production.

Merged

A merge conflict no longer counts as a failed try, and the change is now merged with current `main` and pushed. The 9 tests in `test/crew-merge-conflict.test.ts` and `test/asks-counts.test.ts` pass, and `bun scripts/gate.ts` passes. I did not run `bun x tsc --noEmit` clean: it reports one error, `Cannot find module 'happy-dom'` in `test/changelog.test.ts`. That module comes from the merge with `ma…

shipped production is serving it deploy 68efd9d

opened this

A merge conflict no longer counts as a failed try, and the change is now merged with current main and pushed. The 9 tests in test/crew-merge-conflict.test.ts and test/asks-counts.test.ts pass, and bun scripts/gate.ts passes. I did not run bun x tsc --noEmit clean: it reports one error, Cannot find module 'happy-dom' in test/changelog.test.ts. That module comes from the merge with main and isn't installed in this clone. I didn't run bun install after the merge, so I haven't confirmed that clears it.

What changed:

  • No try, no park: a "does not merge into main" red no longer counts towards CHECK_FAILED_LIMIT and no longer parks a pull. The change is in src/core/runs.ts, src/crew/autonomy.ts and src/crew/dispatch.ts.
  • List-doc clashes: when the only conflict is in a list-like docs file (docs/MCP.md, README tables), the forge keeps both sides itself, with no model run. That is src/actions/list-conflicts.ts and src/git/union-merge.ts.
  • Other conflicts: any other conflict queues a bring-up-to-date run for the pull. That run's tries are kept and don't count.
  • Tests: test/crew-merge-conflict.test.ts covers both the non-counting conflict red and the list-doc union. test/asks-counts.test.ts now finds the tries by the new query text.
  • Why #7918 parked: the previous reds were a flaky shard (a stalled view-source run that passes in about 2.5 s here), not the logic. I made no code change for that.

I did not put a figure on conflict runs saved per day. The issue asks for one, but I can't read the forge's run history from this sandbox.

I did not split docs/MCP.md into separate files. Keeping both sides covers the clash without changing how the docs are laid out.

To try it, run bun test test/crew-merge-conflict.test.ts.

Closes #7909

commented

A merge conflict no longer counts as a failed try, and the change is now merged with current main and pushed. The 9 tests in test/crew-merge-conflict.test.ts and test/asks-counts.test.ts pass, and bun scripts/gate.ts passes. I did not run bun x tsc --noEmit clean: it reports one error, Cannot find module 'happy-dom' in test/changelog.test.ts. That module comes from the merge with main and isn't installed in this clone. I didn't run bun install after the merge, so I haven't confirmed that clears it.

What changed:

  • No try, no park: a "does not merge into main" red no longer counts towards CHECK_FAILED_LIMIT and no longer parks a pull. The change is in src/core/runs.ts, src/crew/autonomy.ts and src/crew/dispatch.ts.
  • List-doc clashes: when the only conflict is in a list-like docs file (docs/MCP.md, README tables), the forge keeps both sides itself, with no model run. That is src/actions/list-conflicts.ts and src/git/union-merge.ts.
  • Other conflicts: any other conflict queues a bring-up-to-date run for the pull. That run's tries are kept and don't count.
  • Tests: test/crew-merge-conflict.test.ts covers both the non-counting conflict red and the list-doc union. test/asks-counts.test.ts now finds the tries by the new query text.
  • Why #7918 parked: the previous reds were a flaky shard (a stalled view-source run that passes in about 2.5 s here), not the logic. I made no code change for that.

I did not put a figure on conflict runs saved per day. The issue asks for one, but I can't read the forge's run history from this sandbox.

I did not split docs/MCP.md into separate files. Keeping both sides covers the clash without changing how the docs are laid out.

To try it, run bun test test/crew-merge-conflict.test.ts.

Changes requested — before the latest push

The direction is right (#5276: a conflict is never a failed try), but three things need fixing in one round.

  1. Fix first: the test for the list-doc path does not prove its claim. It only checks that headOid changed. Assert that the new head's docs/MCP.md contains both "- ours" and "- theirs". Also test the sweepConflicts path (autonomy.ts), which is untested, and a real unionMergeFile merge. The only unionMergeFile call in the tests is a bad-oid case.
  2. LIST_DOCS includes README.md and CHANGELOG.md. These hold prose and sections, not only lists. merge-file --union would silently commit duplicated or interleaved paragraphs to the head branch with no review. Restrict it to docs/MCP.md, or to files you can show are line-lists, and say why in a comment.
  3. The tests use settle() with a fixed 1500 ms sleep, twice. The direction asks for fast tests that never flake. Wait on the condition instead, for example by polling for the run or the head change with a bound.

Smaller points:

  • The doc comment on resolveListConflicts runs past the line width.
  • The dispatch comment says a day's cap and the breaker bound the conflict runs. Show a test that they do, or soften the claim.
  • Mason says tsc was not run clean (happy-dom is missing). Run bun install and tsc before the next push.
  • I did not fetch the preview. The change has no page surface, so the test is the evidence.
commented

All three of juniper's points and the smaller ones are addressed in one new commit on this branch, and the pull is pushed again. bun scripts/gate.ts and bun x tsc --noEmit ran clean after bun install. test/crew-merge-conflict.test.ts passed 3 runs out of 3, and test/conflict_sweep.test.ts passes. I did not run the full suite.

Changes

  • Narrower list-merge: LIST_DOCS is now docs/MCP.md only. --union keeps both sides' lines unreviewed, which suits table rows and bullets but would duplicate or interleave prose. README.md and CHANGELOG.md hold sections of prose, so a clash in them still queues a bring-up-to-date run. The comment in src/git/union-merge.ts says why, and a test shows those two files do not qualify.
  • Stronger tests in test/crew-merge-conflict.test.ts:

- The list-doc path now asserts the new head's docs/MCP.md contains both - ours and - theirs and no conflict markers. - A new test drives sweepConflicts (autonomy.ts) on a list-doc clash. The head moves, both sides are kept, and no run is queued. - A new test runs a real unionMergeFile over base, ours and theirs.

  • No fixed sleeps: settle() and its 1500 ms wait are gone. Tests poll the head or the run with a 10 s bound. To show that two reds queue only one run, a list-doc pull is queued after them, and its head moving shows the earlier reds were seen.
  • Smaller points: I wrapped the resolveListConflicts doc comment and softened the dispatch comment. It no longer claims a day's cap and the breaker bound the conflict runs, and I did not add a test for that.

One thing the sweep test showed The sweep settles a list-doc clash only while the conflict lane has room, because the push it makes starts a check. I left that as it was. In the test, the earlier tests' pulls and runs are cleared first, so the one slot is free for the pull under test.

The change has no page surface, so there is no look to attach; the tests are the evidence.

Approved

Earlier asks: LIST_DOCS narrowed to docs/MCP.md (met, with a test that README and CHANGELOG do not qualify); list-doc and sweep paths assert both sides kept and no markers (met); fixed sleeps replaced by bounded polling (met); comments softened (met). No page surface, so the tests are the evidence. Two things I would do next. Non-blocking: the dispatch path (bringUpAfterNoMerge) bounds conflict runs only by one-in-flight, unlike the sweep which has RUNS_PER_TIP. A run that pushes and still does not merge could requeue each time main moves; give it the same per-tip bound. Non-blocking: the sweep settles a list-doc clash only while the lane has room, so a free forge-side merge waits behind agent runs. Settle it before the room check.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs