ums: separate merge-tree's two forms, stale vs diverged main, untracked R/ files - #1077
Conversation
…ed R/ files Three lessons from ucdavis/bcs#536's post-merge run. batch-merge-and-resolve: the legacy three-arg form and --write-tree carry opposite conflict signals, and each is separately recommended elsewhere in the corpus, so crossing them is the likeliest route to a false all-clear. --write-tree emits no <<<<<<< markers at all, so the fragment's own grep returns 0 unconditionally against it. post-merge: a blocked `git checkout main` reads as the diverged case but is usually just a stale main (0 ahead) plus an unrelated dirty file. Two counts separate them; `git fetch origin main:main` fast-forwards the ref by refspec without a checkout, and refuses rather than clobbering. r-quarto: an untracked file in R/ still gets roxygenized, putting an export() for an invisible function into the tracked NAMESPACE.
|
Driving this PR to clean --- back off until done. |
Code reviewReviewed this UMS PR (three lessons banked into Three issues found, each posted inline with detail:
Considered and set aside as not worth blocking on: a missing explicit Do/Don't pair in the new VerdictNeeds minor changes — three findings above, none blocking on correctness/safety (the prescribed remedies in items 2 and 3 are harmless even where the prose is imprecise), but items 1 and 3 are factual/citation errors worth fixing before merge since this corpus is instructional content that future AI agent sessions will follow directly. |
|
Claude finished review — View run I checked the PR state first, since the review workflow requires stopping if Claude has already reviewed and nothing has changed. Findings:
Since the diff is unchanged since the last review, there is nothing new to evaluate. Per this review workflow's own stop condition ("Claude has already commented on this PR"), and since no SummaryNo new commits since the prior review. The three findings from the previous review (posted 2026-08-03T03:40:10Z) remain outstanding and unaddressed at the current head (
No new issues to add; the prior review already covered this diff in full. VerdictNeeds minor changes — same as the prior verdict, since the diff has not changed. The three findings above are still open. |
…only condition Round 1 findings from claude-review on #1077, all Address. 1. `[ardi](ardi.md)` resolved to shared/workflow/ardi.md, which has zero merge-tree/write-tree occurrences; the supporting usage is in skills/ardi/SKILL.md. Repointed to ../../skills/ardi/SKILL.md, matching the three sibling citations in the same sentence. 2. Called the known-conflicting-pair check a "positive control" while the same file's section heading and case record call it a "negative control". Adopted the file's (and corpus's) established term. Also updated the pre-existing "both failure modes above" to "all three", now stale because this insertion adds a third. 3. `git pull --ff-only` does not fail merely because `ahead > 0` -- with `behind: 0` it reports "Already up to date." and exits 0 (verified empirically). Replaced the ahead-keyed rule with a three-way table over both counts, and relabelled the diverged bullet's condition.
ARD round 1All three findings Addressed in
Two notes on the round. On finding 2, I set aside a real counter-argument rather than silently agreeing: under standard experimental usage a case known to exhibit the effect is the positive control, so the corpus's term is arguably the imprecise one. Internal consistency still wins — one file introducing a competing term is worse than a term with an odd etymology — but changing it belongs in its own PR across all four files, not here. Detail in the thread. Finding 2's second half is the one worth flagging as a process gap: "both failure modes above" is pre-existing text outside my diff, falsified by my insertion. No added-lines-scoped check can see that class of defect. It is the same shape as the deleted-line hazard this very PR documents, arriving from the other direction — an insertion that invalidates neighbouring prose rather than a deletion that removes it. Self-review before pushing: The push carries the re-review; not posting a trigger mention. |
Code review (round 2 — confirming)Re-reviewed against the prior verdict (#1077 (comment)), which flagged three items. All three are fixed in
No new issues in the fix commit itself. VerdictReady for merge. |
|
Claude finished review — View run Code review (round 2 — confirming)Re-reviewed against the prior verdict (#1077 (comment)), which flagged three items. All three are fixed in
No new issues in the fix commit itself. VerdictReady for merge. |
Round 2's cosmetic note. The condition was split out of the bold and the colon re-bolded separately; sibling bullets in this file put the whole label and its colon inside one span.
ARD round 2Round 2's verdict was Ready for merge with no findings, plus one item explicitly marked "not flagged as a finding." Addressing it anyway, in
Two reasons this wasn't left as-is. It also cost nothing, because a SyncMerged
Self-review before pushing: Correcting one thing I got wrong mid-round: I first ran the behind-check in the same command as a push, so the count arrived too late to act on, and then misread The push carries the re-review. |
2026-08-03 04:15 UTC |
Code review (round 3 — confirming)Re-reviewed against the prior verdict (#1077 (comment)), which found the PR ready for merge after all three round-1 findings were fixed. Since then, exactly one new commit landed that's part of this PR's own diff:
No new issues. VerdictReady for merge. |
|
Claude finished review — View run Posted a confirming round-3 review. Summary: the only change since the last "Ready for merge" verdict was a single cosmetic commit that fixed the bold-markup nit I'd flagged as non-blocking in round 2 — everything else in the branch history since then came from merging VerdictReady for merge. |
|
Done --- PR is free. Fully clean at One thing named rather than papered over: Copilot ran and posted nothing. Its |
Three lessons banked from the
post-mergerun onucdavis/bcs#536.Each was hit live during that run, and each is measured rather than recalled.
1.
shared/workflow/batch-merge-and-resolve.md--- the twomerge-treeforms carry opposite signalsThe fragment already documents each form separately: the legacy three-arg form always exits 0 (so grep its output), and
--write-treereports by exit status.It does not say what happens when they are crossed, which is the likeliest mistake, because each half is separately recommended ---
--write-treebyresolve-conflicts,ardi,post-merge, andwrap-up, and the marker grep by this fragment.--write-treeemits no<<<<<<<markers at all.On a conflict it prints the tree OID, three stage entries, and a
CONFLICT (content):line, so the marker grep returns 0 unconditionally, and the existing "match unanchored" fix does not help --- there is nothing to match.Measured on git 2.50.1 against a two-commit synthetic conflict:
<<<<<<<occurrencesmerge-tree --write-tree a bmerge-tree $base a b(legacy)+<<<<<<< .ourAdds the cross-product trap, a Do/Don't pair, and the correct grep for
--write-tree(^CONFLICT).2.
skills/post-merge/SKILL.md--- stalemainis not divergedmainA blocked
git checkout mainreads as the diverged case the skill already warns about, since the symptom is identical.Stale is far commoner: local
mainbehindorigin/mainand 0 ahead, carrying nobody's work.The existing remedy ("skip the pull and delete the branch only") is wrong for that case --- it leaves
mainstale for no reason.What blocks the switch is usually an unrelated dirty file whose content differs between the stale
mainand HEAD, but which is identical between HEAD andorigin/main.git fetch origin main:mainfast-forwards the ref by refspec with no checkout, after which the switch carries the dirty edit across untouched.The refspec form refuses a non-fast-forward rather than clobbering, so it is safe even if the diagnosis is wrong.
On bcs#536: local
mainwas 54 behind, 0 ahead, and blocked on a locally-modifiedrenv.lock.3.
memories/r-quarto.md--- an untracked file inR/poisons the generatedNAMESPACEdocument()reads the working tree, not the index, so an untracked.Rfile still gets roxygenized and its@exportlands in the trackedNAMESPACE.git statusthen shows one innocuous modification while the source backing it is invisible to every other checkout; localR CMD checkpasses because the file is on disk.On bcs#536 an untracked
R/prep_adherence_by_month.Rputexport(prep_adherence_by_month)into adocument()commit.It never reached
mainonly because that commit was never pushed.Verification
check-new-line-breaks(gha): clean over added lines --- it flagged 6 multi-sentence lines in the first draft of item 3, fixed by a reflow before pushing.--write-treenumbers above come from a purpose-built synthetic conflict, not from recollection.🤖 Generated with Claude Code
https://claude.ai/code/session_01XcGPxpt5ZqyWvajP8Nse3v