Skip to content

fix(beads): enrich dependency IDs for parallel graph analysis#323

Merged
subsy merged 3 commits intomainfrom
fix/beads-dependency-enrichment
Feb 20, 2026
Merged

fix(beads): enrich dependency IDs for parallel graph analysis#323
subsy merged 3 commits intomainfrom
fix/beads-dependency-enrichment

Conversation

@subsy
Copy link
Copy Markdown
Owner

@subsy subsy commented Feb 20, 2026

Summary

  • add dependency enrichment in the beads tracker when bd list --json only provides dependency_count
  • query bd dep list --json for tasks that report dependencies and merge/dedupe into dependsOn
  • add defensive filtering for reverse/self rows
  • apply bounded concurrency during enrichment to avoid process fan-out
  • since beads-bv delegates getTasks to beads, it inherits this fix automatically

Test plan

  • bun test src/plugins/trackers/builtin/beads/index.test.ts
  • bun test src/plugins/trackers/builtin/beads-bv/index.test.ts
  • bun run typecheck && bun run build

Summary by CodeRabbit

  • New Features

    • Tracker tasks now receive enriched dependency information for fuller visibility of task relationships.
  • Improvements

    • Dependencies are automatically deduplicated and merged to remove duplicates.
    • Better handling of reverse and self-referential relationships and more robust error handling during dependency retrieval.
    • CLI default execution mode changed to serial when unset; help text updated to reflect defaults.
  • Tests

    • Added test scenarios covering dependency enrichment and deduplication.

@vercel
Copy link
Copy Markdown

vercel bot commented Feb 20, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
ralph-tui Ready Ready Preview, Comment Feb 20, 2026 0:41am

Request Review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Feb 20, 2026

Walkthrough

Added dependency-enrichment to BeadsTrackerPlugin: when bd list returns only dependency counts, the code runs bd dep list for affected tasks, parses/normalises results, merges and deduplicates dependency edges, and filters reverse/self-referential entries before returning tasks.

Changes

Cohort / File(s) Summary
Beads tracker implementation
src/plugins/trackers/builtin/beads/index.ts
Added BdDepListItem interface; implemented enrichDependencies and enrichTaskDependencies; batch processing with concurrency limit; runs bd dep list, parses JSON (accepts type or dependency_type), filters edges, merges/deduplicates into task.dependsOn; integrated enrichment into getTasks; added error handling for command failures and parse errors.
Beads tracker tests
src/plugins/trackers/builtin/beads/index.test.ts
Added tests covering enrichment when bd list returns only dependency_count: extra dep-list lookup, merging/deduplication, and ignoring reverse/self edges.
CLI run defaults
src/commands/run.tsx
Changed default parallel mode fallback from auto to never when unset; updated help text for --serial/--parallel to reflect serial default and worker wording.

Sequence Diagram

sequenceDiagram
    autonumber
    participant getTasks as getTasks()
    participant enrichDeps as enrichDependencies()
    participant enrichTask as enrichTaskDependencies()
    participant bdCmd as bd dep list
    participant Task as TrackerTask

    getTasks->>enrichDeps: pass filtered tasks + rawBeads
    enrichDeps->>enrichDeps: compute dependency counts<br/>select tasks needing enrichment
    enrichDeps->>enrichTask: dispatch tasks (batched, max 8 concurrent)
    enrichTask->>bdCmd: run `bd dep list` for Task
    bdCmd-->>enrichTask: return BdDepListItem[] (JSON)
    enrichTask->>enrichTask: parse/normalise items<br/>filter out reverse/self edges<br/>merge & dedupe
    enrichTask->>Task: update Task.dependsOn
    enrichTask-->>enrichDeps: task enriched
    enrichDeps-->>getTasks: return tasks with enriched dependencies
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • PR #308 — Normalises bd dep list JSON fields (dependency_type vs type) which directly aligns with the new BdDepListItem parsing.
  • PR #109 — Related changes to BeadsTrackerPlugin dependency handling (uses bd ready for task selection), complementary to this enrichment workflow.
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately captures the main change: implementing dependency enrichment in the beads tracker plugin for parallel graph analysis, which aligns with the primary modifications across both test and implementation files.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/beads-dependency-enrichment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link
Copy Markdown

codecov bot commented Feb 20, 2026

Codecov Report

❌ Patch coverage is 65.11628% with 30 lines in your changes missing coverage. Please review.
✅ Project coverage is 45.44%. Comparing base (25b5107) to head (9c40ec8).
⚠️ Report is 4 commits behind head on main.

Files with missing lines Patch % Lines
src/plugins/trackers/builtin/beads/index.ts 65.47% 29 Missing ⚠️
src/commands/run.tsx 50.00% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #323      +/-   ##
==========================================
+ Coverage   45.39%   45.44%   +0.05%     
==========================================
  Files          98       98              
  Lines       31412    31496      +84     
==========================================
+ Hits        14258    14313      +55     
- Misses      17154    17183      +29     
Files with missing lines Coverage Δ
src/commands/run.tsx 12.03% <50.00%> (ø)
src/plugins/trackers/builtin/beads/index.ts 69.76% <65.47%> (-0.57%) ⬇️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
src/plugins/trackers/builtin/beads/index.test.ts (1)

447-539: Good coverage of the happy-path enrichment scenarios.

The three new tests cover the core enrichment flow, merge/dedup, and defensive filtering well. Consider adding tests for the two error/fallback branches in enrichTaskDependencies:

  1. Non-zero exit from bd dep list — verifies the task's existing dependsOn is preserved and no crash occurs.
  2. Unparseable JSON from bd dep list — verifies the catch fallback path.
  3. dependency_type field variant — all current tests use the type field; a test using dependency_type instead would exercise the coalescing logic at line 479 of index.ts.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/plugins/trackers/builtin/beads/index.test.ts` around lines 447 - 539, Add
three unit tests exercising enrichTaskDependencies error/fallback branches: (1)
simulate a non-zero exit from the bd dep list spawn response and assert existing
task.dependsOn is preserved and no exception is thrown (use
createInitializedPlugin and plugin.getTasks as in other tests), (2) simulate
unparseable JSON stdout from bd dep list and assert the catch fallback preserves
existing dependsOn, and (3) simulate dependency rows that use dependency_type
instead of type to verify the coalescing logic in enrichTaskDependencies picks
up that field; reference the same mockSpawnResponses and mockSpawnArgs pattern
used in the existing tests to drive each scenario.
src/plugins/trackers/builtin/beads/index.ts (1)

432-455: Consider skipping enrichment for tasks whose dependencies are already fully populated.

Currently every task with dependency_count > 0 triggers a bd dep list subprocess, even when the initial bd list output already provided the full dependencies array. For large task sets this could double the number of subprocess calls unnecessarily.

♻️ Suggested optimisation
-    const tasksToEnrich = tasks.filter((t) => depCountMap.has(t.id));
+    const tasksToEnrich = tasks.filter((t) => {
+      const expectedCount = depCountMap.get(t.id);
+      if (expectedCount === undefined) return false;
+      // Skip if existing dependsOn already matches the advertised count
+      return (t.dependsOn?.length ?? 0) < expectedCount;
+    });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/plugins/trackers/builtin/beads/index.ts` around lines 432 - 455, Skip
calling enrichTaskDependencies for tasks whose dependencies are already
complete: in enrichDependencies, when building tasksToEnrich, check each
TrackerTask's dependencies array length against the raw bead's dependency_count
(use depCountMap or raw.dependency_count lookup) and only include tasks where
dependency_count is greater than the existing task.dependencies.length; keep the
batching/concurrency logic and still call this.enrichTaskDependencies(task) only
for those that need additional enrichment.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/plugins/trackers/builtin/beads/index.test.ts`:
- Around line 447-539: Add three unit tests exercising enrichTaskDependencies
error/fallback branches: (1) simulate a non-zero exit from the bd dep list spawn
response and assert existing task.dependsOn is preserved and no exception is
thrown (use createInitializedPlugin and plugin.getTasks as in other tests), (2)
simulate unparseable JSON stdout from bd dep list and assert the catch fallback
preserves existing dependsOn, and (3) simulate dependency rows that use
dependency_type instead of type to verify the coalescing logic in
enrichTaskDependencies picks up that field; reference the same
mockSpawnResponses and mockSpawnArgs pattern used in the existing tests to drive
each scenario.

In `@src/plugins/trackers/builtin/beads/index.ts`:
- Around line 432-455: Skip calling enrichTaskDependencies for tasks whose
dependencies are already complete: in enrichDependencies, when building
tasksToEnrich, check each TrackerTask's dependencies array length against the
raw bead's dependency_count (use depCountMap or raw.dependency_count lookup) and
only include tasks where dependency_count is greater than the existing
task.dependencies.length; keep the batching/concurrency logic and still call
this.enrichTaskDependencies(task) only for those that need additional
enrichment.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/commands/run.tsx (1)

599-599: (default workers: 3) in help text may not reflect stored config.

The actual default resolves as storedConfig?.parallel?.maxWorkers ?? 3 (line 3119), so the stated "3" is only accurate when no maxWorkers is persisted. Users who have configured a different value in their project config would see a misleading hint.

✏️ Suggested wording
-  --parallel [N]      Force parallel execution with optional max workers (default workers: 3)
+  --parallel [N]      Force parallel execution with optional max workers (default: 3, or value from config)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/commands/run.tsx` at line 599, The help string that currently reads
"--parallel [N]      Force parallel execution with optional max workers (default
workers: 3)" is misleading because the real default is computed as
storedConfig?.parallel?.maxWorkers ?? 3; update the help text generation in
src/commands/run.tsx to reflect the actual default by computing the effective
default (e.g., const effectiveDefault = storedConfig?.parallel?.maxWorkers ?? 3)
and inserting that value into the help string or rewording to "default: config
value or 3" so the displayed hint matches the value used at runtime.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/commands/run.tsx`:
- Line 599: The help string that currently reads "--parallel [N]      Force
parallel execution with optional max workers (default workers: 3)" is misleading
because the real default is computed as storedConfig?.parallel?.maxWorkers ?? 3;
update the help text generation in src/commands/run.tsx to reflect the actual
default by computing the effective default (e.g., const effectiveDefault =
storedConfig?.parallel?.maxWorkers ?? 3) and inserting that value into the help
string or rewording to "default: config value or 3" so the displayed hint
matches the value used at runtime.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant