Skip to content

Commit bd003df

Browse files
Copilotneongreen
andcommitted
Add beads-merge: jj merge driver for .jsonl files
Co-authored-by: neongreen <1523306+neongreen@users.noreply.github.com>
1 parent 35712a2 commit bd003df

9 files changed

Lines changed: 1319 additions & 0 deletions

File tree

.github/workflows/beads-merge.yml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
name: beads-merge
2+
3+
on:
4+
push:
5+
paths:
6+
- "beads-merge/**"
7+
- ".github/workflows/beads-merge.yml"
8+
pull_request:
9+
paths:
10+
- "beads-merge/**"
11+
- ".github/workflows/beads-merge.yml"
12+
13+
jobs:
14+
test:
15+
runs-on: ubuntu-latest
16+
17+
steps:
18+
- name: Checkout code
19+
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
20+
with:
21+
persist-credentials: false
22+
23+
- name: Set up Go
24+
uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0
25+
with:
26+
go-version: "1.24.7"
27+
cache-dependency-path: beads-merge/go.sum
28+
29+
- name: Run tests
30+
working-directory: beads-merge
31+
run: go test ./... -v
32+
33+
- name: Build
34+
working-directory: beads-merge
35+
run: go build -o beads-merge .

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ This repository contains multiple independent projects.
1010
| [markdown-format](markdown-format/) | alpha | Markdown formatter; command surface and formatting rules are still evolving. |
1111
| [prrun](prrun/) | beta | Runs binaries from PR releases to speed up verification workflows. |
1212
| [printpdf](printpdf/) | alpha | Markdown/web-to-PDF tool; rendering pipeline has known gaps documented in project issues. |
13+
| [beads-merge](beads-merge/) | alpha | 3-way merge tool for beads `.jsonl` issue files; designed for jj version control. |
1314
| [ingest](ingest/) | pre-alpha | Data ingestion orchestrator; schema and connectors change frequently. |
1415
| [diagram-dsl](diagram-dsl/) | experimental | TypeScript DSL for diagrams; layout system under active refactor. |
1516
| [mdbook-comments](mdbook-comments/) | alpha | mdbook preprocessor for paragraph-level commenting with Supabase backend. |

beads-merge/README.md

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
# beads-merge
2+
3+
A 3-way merge tool for beads `.jsonl` issue tracker files, designed to work with jj (Jujutsu version control).
4+
5+
## Overview
6+
7+
`beads-merge` intelligently merges beads issue tracker files by:
8+
9+
- Matching issues by their unique key (`.id`, `.created_at`, `.created_by`)
10+
- Applying smart merge rules for each field
11+
- Combining dependency arrays and removing duplicates
12+
- Outputting conflict markers for unresolvable conflicts
13+
14+
## Usage
15+
16+
```bash
17+
beads-merge <base-file> <left-file> <right-file>
18+
```
19+
20+
The tool reads three versions of a `.jsonl` file and outputs the merged result to stdout.
21+
22+
### As a jj Merge Tool
23+
24+
Configure in your jj config (e.g., `~/.jjconfig.toml`):
25+
26+
```toml
27+
[merge-tools.beads-merge]
28+
program = "beads-merge"
29+
merge-args = ["$base", "$left", "$right"]
30+
```
31+
32+
Then use it with:
33+
34+
```bash
35+
jj resolve --tool=beads-merge
36+
```
37+
38+
## Merge Algorithm
39+
40+
### Issue Matching
41+
42+
Issues are matched by their composite key:
43+
- `.id` - Issue identifier
44+
- `.created_at` - Creation timestamp
45+
- `.created_by` - Creator identifier
46+
47+
### Field Merging Rules
48+
49+
For matched issues, fields are merged as follows:
50+
51+
**String fields** (title, description, notes, status, issue_type):
52+
- If base == left and base != right: take right
53+
- If base == right and base != left: take left
54+
- Otherwise: take left (including when both changed to same value)
55+
56+
**Priority** (integer):
57+
- Same logic as string fields
58+
59+
**Timestamps** (updated_at, closed_at):
60+
- Take the maximum (latest) value
61+
- If one is null, take the non-null value
62+
63+
**Dependencies** (array):
64+
- Combine arrays from both sides
65+
- Remove duplicates based on (issue_id, depends_on_id, type)
66+
67+
### Conflict Handling
68+
69+
Conflicts are output in standard merge conflict format:
70+
71+
```
72+
<<<<<<< left
73+
{"id":"bd-1","title":"Left version",...}
74+
=======
75+
{"id":"bd-1","title":"Right version",...}
76+
>>>>>>> right
77+
```
78+
79+
Conflicts occur when:
80+
- An issue is modified in both branches with incompatible changes to the same field
81+
- An issue is added in both branches with different content
82+
- An issue is modified in one branch and deleted in the other
83+
84+
## Building
85+
86+
```bash
87+
# Run tests
88+
mise run //beads-merge:test
89+
90+
# Build binary
91+
mise run //beads-merge:build
92+
93+
# Format code
94+
mise run //beads-merge:fmt
95+
```
96+
97+
## Examples
98+
99+
### Simple merge
100+
101+
Base:
102+
```jsonl
103+
{"id":"bd-1","title":"Original","status":"open","created_at":"2025-10-16T20:51:29+02:00","created_by":"user1"}
104+
```
105+
106+
Left (updated title):
107+
```jsonl
108+
{"id":"bd-1","title":"Updated","status":"open","created_at":"2025-10-16T20:51:29+02:00","created_by":"user1"}
109+
```
110+
111+
Right (changed status):
112+
```jsonl
113+
{"id":"bd-1","title":"Original","status":"closed","created_at":"2025-10-16T20:51:29+02:00","created_by":"user1"}
114+
```
115+
116+
Result (both changes merged):
117+
```jsonl
118+
{"id":"bd-1","title":"Updated","status":"closed","created_at":"2025-10-16T20:51:29+02:00","created_by":"user1"}
119+
```
120+
121+
### Dependency merge
122+
123+
Left adds dependency on bd-2, right adds dependency on bd-3:
124+
125+
Result combines both dependencies without duplicates.
126+
127+
## Exit Codes
128+
129+
- `0` - Successful merge with no conflicts
130+
- `1` - Conflicts present (conflict markers in output) or error occurred

beads-merge/go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module github.com/neongreen/mono/beads-merge
2+
3+
go 1.24.7

beads-merge/go.sum

Whitespace-only changes.

0 commit comments

Comments
 (0)