Skip to content

Commit 3f55b2a

Browse files
authored
feat(import): add Beads JSONL import with selective issue trees (#124)
Fixes #121 Add --beads <path> and optional issue IDs to import selected issue trees. Map Beads metadata and dependency links into Dex task fields. Preserve completed_at when closed issues are re-imported without closed_at. Add fixtures, parser coverage, and CLI/docs updates for this import flow.
1 parent 939f6cb commit 3f55b2a

17 files changed

Lines changed: 1373 additions & 29 deletions

docs/src/pages/cli.astro

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,15 +243,17 @@ dex sync --dry-run # Preview sync`}
243243

244244
<div class="command-card">
245245
<h3>dex import</h3>
246-
<div class="synopsis">dex import &lt;ref&gt; [options]</div>
247-
<p>Import a GitHub Issue or Shortcut Story as a dex task.</p>
246+
<div class="synopsis">dex import &lt;ref&gt; [options] | dex import --beads &lt;path&gt; [issue-id...] [options]</div>
247+
<p>Import a GitHub Issue, Shortcut Story, or Beads JSONL export as dex tasks.</p>
248248
<ul>
249249
<li><code>--all</code> — Import all items with the dex label</li>
250+
<li><code>--beads &lt;path&gt;</code> — Import from Beads JSONL export file</li>
250251
<li><code>--github</code> — Filter <code>--all</code> to only GitHub</li>
251252
<li><code>--shortcut</code> — Filter <code>--all</code> to only Shortcut</li>
252253
<li><code>--update</code> — Update existing task if already imported</li>
253254
<li><code>--dry-run</code> — Preview what would be imported</li>
254255
</ul>
256+
<p><strong>Beads selection:</strong> pass one or more issue IDs after <code>--beads &lt;path&gt;</code> to import only those issues and their descendants.</p>
255257
<p><strong>Reference formats:</strong></p>
256258
<ul>
257259
<li>GitHub: <code>#123</code>, <code>owner/repo#123</code>, or full URL</li>
@@ -261,6 +263,8 @@ dex sync --dry-run # Preview sync`}
261263
<Code
262264
code={`dex import #42 # Import GitHub issue #42
263265
dex import sc#123 # Import Shortcut story #123
266+
dex import --beads ./beads.jsonl # Import all from Beads export
267+
dex import --beads ./beads.jsonl issue-1 issue-2 # Import selected Beads issues + descendants
264268
dex import https://github.com/owner/repo/issues/42
265269
dex import https://app.shortcut.com/myorg/story/123
266270
dex import --all # Import all dex-labeled items

specs/beads-import.md

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# Beads Import (MVP)
2+
3+
Add `dex import --beads <path> [issue-id...]` to ingest Beads JSONL exports into Dex tasks.
4+
5+
## Goals
6+
7+
- Import Beads issue graphs without adding a full sync integration.
8+
- Preserve Beads provenance in task metadata.
9+
- Keep imports idempotent and safe to re-run.
10+
- Keep existing GitHub/Shortcut import flows unchanged.
11+
12+
## CLI Contract
13+
14+
- New flag: `--beads <path>`
15+
- Supported with:
16+
- `--dry-run`
17+
- `--update`
18+
- Optional positional arguments in Beads mode:
19+
- `[issue-id...]` to import one or more root Beads issues and all descendants
20+
- Invalid combinations:
21+
- `--beads` with `--all`, `--github`, or `--shortcut`
22+
23+
## Data Mapping
24+
25+
- `id` -> task `id`
26+
- `title` -> task `name`
27+
- `description` -> task `description`
28+
- `priority` -> task `priority`
29+
- `status=closed` (or `closed_at` present) -> `completed=true`
30+
- `created_at`, `updated_at`, `closed_at` -> task timestamps
31+
- `status in {in_progress, hooked}` -> `started_at` (best-effort from `updated_at`)
32+
- Dependency type `parent-child` -> task `parent_id`
33+
- Dependency type `blocks` -> task `blockedBy`
34+
- Non-blocking dependency types are preserved in `metadata.beads` and not mapped to Dex relationships.
35+
36+
## Implementation Shape
37+
38+
- Add Beads parser/normalizer under `src/core/beads/`.
39+
- Extend task metadata schema with `metadata.beads` in `src/types.ts`.
40+
- Extend `src/cli/import.ts` to handle `--beads` branch.
41+
- Apply import in two passes:
42+
1. Upsert task fields (create/update)
43+
2. Apply relationships (parent + blockers)
44+
45+
Relationship failures (depth/cycle/missing target) should produce warnings and continue.
46+
47+
## Test Strategy
48+
49+
- Parser tests in `src/core/beads/import.test.ts`:
50+
- valid JSONL parsing
51+
- dependency normalization
52+
- malformed line handling (line number in error)
53+
- CLI tests in `src/cli/import.test.ts`:
54+
- happy path import
55+
- dry-run no writes
56+
- update semantics
57+
- invalid flag combinations
58+
- relationship warnings do not abort import
59+
- Schema test in `src/types.test.ts` for `metadata.beads` compatibility.
60+
61+
## Anonymized Fixtures
62+
63+
- Add anonymized Beads-derived fixtures under `src/core/beads/fixtures/`.
64+
- Produce fixture data from local Beads exports via an external/local workflow that:
65+
- pseudonymizes IDs/actors/labels/external refs
66+
- redacts free-text fields
67+
- preserves graph shape, status mix, priorities, and dependency semantics
68+
69+
No raw Beads state or secret-bearing exports are committed.

src/cli/help.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ ${colors.bold}COMMANDS:${colors.reset}
5050
import #N Import GitHub issue
5151
import sc#N Import Shortcut story
5252
import --all Import all dex-labeled items
53+
import --beads <path> Import tasks from Beads JSONL export
5354
export <id>... Export tasks to GitHub (no sync back)
5455
completion <shell> Generate shell completion script
5556
@@ -102,9 +103,11 @@ ${colors.bold}EXAMPLES:${colors.reset}
102103
dex sync --dry-run # Preview what would be synced
103104
104105
${colors.dim}# Import from external services:${colors.reset}
105-
dex import #42 # Import GitHub issue #42
106-
dex import sc#123 # Import Shortcut story #123
107-
dex import --all # Import all dex-labeled items
108-
dex import --all --shortcut # Import only from Shortcut
106+
dex import #42 # Import GitHub issue #42
107+
dex import sc#123 # Import Shortcut story #123
108+
dex import --all # Import all dex-labeled items
109+
dex import --all --shortcut # Import only from Shortcut
110+
dex import --beads ./beads.jsonl # Import all from Beads export
111+
dex import --beads ./beads.jsonl id1 id2 # Import selected Beads trees
109112
`);
110113
}

0 commit comments

Comments
 (0)