Implement bd-10: Export/import dependencies in JSONL

Added dependency support to export/import workflow:

Changes:
- Added GetDependencyRecords() to Storage interface to get raw dependency records
- Extended Issue struct with Dependencies field (omitempty for backward compat)
- Modified export.go to populate dependencies for each issue
- Modified import.go to process dependencies in second pass after all issues exist
- All tests pass

Benefits:
- JSONL is now self-contained with full dependency information
- Enables proper collision resolution in future (bd-12+)
- Idempotent imports: existing dependencies are not duplicated
- Forward references handled: dependencies created after all issues exist

Example output:
{
  "id": "bd-10",
  "title": "...",
  "dependencies": [{
    "issue_id": "bd-10",
    "depends_on_id": "bd-9",
    "type": "parent-child",
    "created_at": "...",
    "created_by": "stevey"
  }]
}

Closes bd-10

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Steve Yegge
2025-10-12 15:08:05 -07:00
parent 216f640ab4
commit 8d3bbbcc52
6 changed files with 128 additions and 32 deletions

View File

@@ -178,6 +178,38 @@ func (s *SQLiteStorage) GetDependents(ctx context.Context, issueID string) ([]*t
return scanIssues(rows)
}
// GetDependencyRecords returns raw dependency records for an issue
func (s *SQLiteStorage) GetDependencyRecords(ctx context.Context, issueID string) ([]*types.Dependency, error) {
rows, err := s.db.QueryContext(ctx, `
SELECT issue_id, depends_on_id, type, created_at, created_by
FROM dependencies
WHERE issue_id = ?
ORDER BY created_at ASC
`, issueID)
if err != nil {
return nil, fmt.Errorf("failed to get dependency records: %w", err)
}
defer rows.Close()
var deps []*types.Dependency
for rows.Next() {
var dep types.Dependency
err := rows.Scan(
&dep.IssueID,
&dep.DependsOnID,
&dep.Type,
&dep.CreatedAt,
&dep.CreatedBy,
)
if err != nil {
return nil, fmt.Errorf("failed to scan dependency: %w", err)
}
deps = append(deps, &dep)
}
return deps, nil
}
// GetDependencyTree returns the full dependency tree
func (s *SQLiteStorage) GetDependencyTree(ctx context.Context, issueID string, maxDepth int) ([]*types.TreeNode, error) {
if maxDepth <= 0 {