Repository navigation
feat(resolve): merge concurrent quest link-list edits with a git merge driver - #219
Conversation
Quest-Claim: 6422ed0ec3f17c33
…e driver quest resolve merges by lines with git merge-file, then resolves each conflict that only edits the entries of one Required, Related, or Closes list: removals stay removed, inserts from either side are kept in place (ours first), and a one-sided edit wins. Anything else keeps conflict markers. quest init writes quest/** merge=quest to .gitattributes and sets merge.quest.driver; any other command registers the driver when the attributes name it, and uninstall removes both. Without a quest that has resolve on PATH, the driver falls back to git merge-file. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
@codex security review (Written by Claude Opus 5.5) |
|
Codex Review: Didn't find any major issues. Keep it up! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
# Conflicts: # quest/m0/helpers/README.md
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 53bfbadb14
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
A reference-style link's destination lives in a definition outside the conflict, which the clean regions show only as merged. A side that re-targeted the entry there looked unchanged, so a remove on the other side silently dropped it. Resolve only entries whose own lines carry their destination. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Landing summary
Landing 43a3bd4 with a squash merge. (Written by Claude Opus 5.5) |
Finishes quest/m0/helpers/resolve.md and deletes it.
Problem
Concurrent PRs keep conflicting on quest link lists:
maindeletes finished quests' lines while a branch inserts a new quest beside them. Git's line merge reports these as conflicts even though the intent of both sides is clear.Behavior
quest resolve <ours> <base> <theirs>is a git merge driver. It runsgit merge-file --diff3, then resolves each conflict that consists only of whole entries of oneRequired,Related, orCloseslist, each opening with a link (matched by that link's destination, using the real Markdown parser on each side's full document). Base entries neither side removed are kept, taking a one-sided edit; entries either side inserted are placed after the entry preceding them on that side, ours before theirs; an entry both sides inserted identically appears once. The result goes to<ours>; it exits 1 when conflicts remain.quest initappendsquest/** merge=questto.gitattributesand setsmerge.quest.driverin the clone's local config. Any other command sets the config when.gitattributesnamesmerge=questand no config sets the driver, so fresh clones and worktrees pick it up. Config writes happen only inside a git work tree and never fail a command.quest uninstallremoves the line and themerge.questconfig section.if quest help resolve >/dev/null 2>&1; then quest resolve %A %O %B; else git merge-file -L ours -L base -L theirs %A %O %B; fi,so a missing
quest, or an older one withoutresolve, gives today's conflict markers..gitattributesgets the line too, and the guide, README, and SETUP.md describe the driver and its GitHub limitation.Choices made without asking
quest help resolve, notquest resolve --help. The plan named the latter, but commander prints the top-level help and exits 0 forquest <unknown> --help, so an older binary would pass the probe and then fail the merge.quest help <unknown>exits 2. The lifecycle check now asserts both behaviors on the built binaries.sh -c. Git already runs drivers through a shell, so the registered command is theif/then/elseitself, with%A %O %Bsubstituted directly.merge.conflictStyle: they include the base section fordiff3/zdiff3. Markers are 7 characters and labeledours/base/theirs, like the fallback.%L,%X, and%Yaren't passed. Analysis uses markers longer than any marker-like run in the inputs, so a setext=======underline can't be mistaken for one.initwrites.gitattributeseven beforegit init. Only the config write needs a work tree. Self-healing later registers the driver.quest checkto flag. It already reports both.Validation
just checkandjust testpass locally: vitest, hook suites, and the lifecycle check ondist/quest.jsand the compileddist/quest.test/resolve.test.tscovers the common delete-beside-insert shape, insert ordering, duplicate inserts, one-sided edits, wrapped entries, CRLF, the fail-closed cases, a mixed prose+list file, heading-spanning conflicts, lists outside link sections, and marker-like content. It also runs a realgit mergewith the driver on PATH (resolves) and without it (falls back to markers), and checks registration, self-healing, and uninstall.quest check --base origin/mainpasses.Limitations
questis on the merge's PATH. In this repository's dev setup (bun run quest), it falls back.Suggested follow-ups
%L/%X/%Yso unresolved markers match git's own labels and size.🤖 Generated with Claude Code
(Written by Claude Opus 5.5)