Skip to content

Improve beads tracker detection and markdown PRD handling#232

Merged
subsy merged 5 commits intomainfrom
claude/improve-beads-detection-uscDL
Jan 27, 2026
Merged

Improve beads tracker detection and markdown PRD handling#232
subsy merged 5 commits intomainfrom
claude/improve-beads-detection-uscDL

Conversation

@subsy
Copy link
Owner

@subsy subsy commented Jan 27, 2026

Summary

This PR enhances the beads tracker support and adds better error handling for markdown PRD files. It improves tracker detection to check for actual availability (CLI and .beads directory), adds support for the new beads-rust tracker variant, and provides helpful guidance when users attempt to use markdown files with the --prd flag.

Key Changes

  • Markdown PRD validation: Added early detection and helpful error message when users try to use markdown files with --prd flag, directing them to use the convert command instead
  • Beads tracker detection: Enhanced detectTrackerPlugins() to actually check for tracker availability by:
    • Calling initialize() and isReady() on tracker instances
    • Invoking detect() method on beads-family trackers to get granular error information
    • Capturing specific error reasons (missing .beads directory vs missing CLI binary)
  • beads-rust support: Added beads-rust as a recognized beads-family tracker variant throughout the codebase
  • Improved error messaging: Created formatTrackerUnavailableReason() helper to provide specific, actionable guidance based on what's missing (e.g., "bd CLI not found. Install it to use this tracker.")
  • Better UX in setup wizard:
    • Display unavailable trackers with clear "(unavailable)" labels
    • Show specific reasons why trackers aren't available
    • Added helpful tips for beads tracker users about epic selection and markdown conversion
    • Provide tracker-specific next steps after setup
  • Removed unused import: Removed direct BeadsTrackerPlugin import and replaced instanceof check with duck-typing (tracker.setEpicId method check)

Implementation Details

  • The tracker detection now properly initializes instances with empty config to trigger environment checks
  • Beads-family trackers can now report specific errors (directory not found, CLI not available) through their detect() method
  • The setup wizard provides contextual guidance based on tracker availability and type
  • All beads variants (beads, beads-bv, beads-rust) are treated consistently throughout the codebase

https://claude.ai/code/session_01UrVoS4wbY85XkszHLo2guX

Summary by CodeRabbit

  • New Features

    • Added support for the beads-rust tracker and expanded interactive epic-selection guidance; wizard labels tracker availability, shows clear reasons when unavailable, and surfaces beads-specific run/PRD conversion tips.
    • CLI now warns about Markdown PRD files, suggests conversion commands and exits with an error.
  • Bug Fixes

    • Tracker selection now checks for reported capabilities instead of relying on a specific tracker type.
  • Tests

    • Expanded tests for tracker detection, unavailable-reason messaging and Markdown PRD handling.

✏️ Tip: You can customize this high-level summary in your review settings.

- Enhance setup wizard to actually detect tracker availability by
  initializing plugins and checking .beads directory + CLI presence
- Show unavailable trackers with specific reasons (missing directory,
  missing CLI) and guidance on how to fix
- Add tip messages after selecting a Beads tracker with epic ID usage
  and markdown PRD conversion guidance
- Detect markdown PRD files passed to --prd flag and show clear error
  with conversion commands instead of silently failing
- Include beads-rust in epic selection flow alongside beads and beads-bv
- Use interface-based setEpicId check instead of instanceof for broader
  tracker compatibility

https://claude.ai/code/session_01UrVoS4wbY85XkszHLo2guX
@vercel
Copy link

vercel bot commented Jan 27, 2026

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

1 Skipped Deployment
Project Deployment Review Updated (UTC)
ralph-tui Ignored Ignored Preview Jan 27, 2026 0:41am

Request Review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 27, 2026

Walkthrough

This PR adds beads‑rust to beads‑family tracker recognition, replaces a BeadsTrackerPlugin type check with a feature check (setEpicId) when assigning epics, exports formatTrackerUnavailableReason, refactors tracker detection to report availability/version/errors, surfaces beads‑specific run/PRD conversion guidance in the setup wizard, and rejects Markdown PRDs with conversion instructions and exit(1).

Changes

Cohort / File(s) Summary
Run CLI & PRD handling
src/commands/run.tsx
Remove direct import/type‑check of BeadsTrackerPlugin; use feature check (setEpicId) to assign epics. Add markdown PRD detection for --prd that prints conversion guidance and exits non‑zero for .md/.markdown files.
Config: tracker recognition & warnings
src/config/index.ts, src/config/index.test.ts
Recognise beads-rust alongside existing beads variants. Vary missing‑epic‑id warning by UI mode (TUI vs headless). Tests added/renamed to cover beads‑rust and TUI/headless behaviours.
Setup wizard detection & messaging
src/setup/wizard.ts, src/setup/wizard.test.ts
Introduce detection flow that captures per‑plugin available/version/error; add/export formatTrackerUnavailableReason(plugin: PluginDetection): string; label unavailable trackers and surface beads‑family run/PRD conversion tips. Tests expanded with deterministic mocks and many detection scenarios.
CLI tests: markdown PRD detection
tests/commands/run.test.ts
New tests asserting .md/.markdown/.MD passed to --prd emit helpful ralph-tui convert suggestions and call process.exit(1); .json accepted; conversion command paths validated.
CI workflow
.github/workflows/ci.yml
Change coverage threshold extraction to use per‑batch line coverage (LINES_COV) and fail if below 40%; adjust output/messaging to reference line coverage.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Wizard as "Setup Wizard"
    participant Detector as "Tracker Detector"
    participant Plugin as "Tracker Plugin"
    participant UI as "CLI/UI"

    User->>Wizard: Start setup wizard
    Wizard->>Detector: detectTrackerPlugins(cwd)
    Detector->>Plugin: createInstance / instantiate
    Plugin->>Detector: isReady() / optional detect(cwd)
    alt plugin has detect()
        Detector->>Plugin: detect(cwd)
        Plugin-->>Detector: { available?, version?, error? }
    else no detect()
        Plugin-->>Detector: available=true (no env reqs)
    end
    Detector-->>Wizard: plugin detection results (available/version/error)
    Wizard->>Wizard: formatTrackerUnavailableReason(plugin)
    Wizard->>UI: render tracker choices (mark unavailable / show reasons)
    User->>Wizard: select tracker
    alt beads-family selected & available
        Wizard->>UI: show beads-specific run & PRD-conversion tips
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐇 I sniffed the plugins, found a Rusty friend,

Beads now welcome — no brittle end,
If a tracker hides, I'll tell you why,
And show the convert command to try,
Hop onwards, runner — give that PRD a try 🥕

🚥 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 summarises the two main changes: beads tracker detection improvements and markdown PRD error handling.
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.


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.

Copy link
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.

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In `@src/config/index.ts`:
- Around line 645-653: The current beads tracker warning uses a single message
that claims an "interactive epic selection" will be shown even in headless mode;
update the branch where config.tracker.plugin is 'beads'|'beads-bv'|'beads-rust'
and config.epicId is falsy to choose the warning based on config.showTui: if
config.showTui is true, keep the existing interactive-selection wording,
otherwise replace it with a headless-appropriate message (e.g., "No epic ID
specified for beads tracker; running headless so no interactive epic selection
available") so the warnings array reflects the actual runtime mode; modify the
check around config.epicId and push the appropriate string accordingly.

In `@src/setup/wizard.ts`:
- Around line 60-83: In formatTrackerUnavailableReason (PluginDetection),
restrict the beads-specific heuristics so they only run for beads trackers:
check plugin.id for beads family (e.g., plugin.id === 'beads' or plugin.id ===
'beads-rust' or plugin.id.startsWith('beads')) before evaluating plugin.error
for "directory not found" or "not available"; for the binary branch derive cli
via plugin.id === 'beads-rust' ? 'br' : 'bd' as before, otherwise skip those
branches and fall back to returning plugin.error or `${plugin.description} (not
detected)` to avoid misattributing non‑beads tracker errors.
- Around line 104-129: Wrap the per-tracker sequence (calling
instance.initialize(), instance.isReady(), and the optional instance.detect())
in a try/catch/finally so any thrown errors are caught, instance.dispose() is
always called in finally, and a detection entry is still pushed to detections
with available: false and error set to the caught error message (e.g.,
"unavailable" or error.toString()) and version left undefined; specifically
update the block around instance.initialize, instance.isReady, the
instanceAsDetectable.detect call, and the final detections.push to ensure errors
don't abort the wizard and dispose() always runs.

- Add 6 direct unit tests for formatTrackerUnavailableReason covering all
  branches: directory not found, CLI not available (bd vs br), generic
  error fallback, and no-error fallback
- Add 5 integration tests for tracker detection in setup wizard: verifying
  beads trackers show as unavailable without CLI, json tracker is always
  available, unavailable reasons contain helpful guidance, beads-rust
  mentions br CLI specifically, and default selection falls to json
- Add 3 tests for epic-specific instructions shown after selecting beads,
  beads-bv, and beads-rust trackers in setup wizard
- Add 5 tests for markdown PRD detection in run command: .md, .markdown,
  case-insensitive .MD, non-rejection of .json, and correct file paths
  in convert command suggestions
- Add 1 test for beads-rust tracker validation warning about missing epic
  ID with updated "interactive epic selection" message
- Export formatTrackerUnavailableReason for direct testability
- Fix detectTrackerPlugins to use detect() method directly instead of
  initialize()+isReady(), avoiding false unavailability for json tracker

Coverage: wizard.ts 87%, run.tsx markdown detection fully covered,
config/index.ts validation fully covered.

https://claude.ai/code/session_01UrVoS4wbY85XkszHLo2guX
Copy link
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.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@src/setup/wizard.test.ts`:
- Around line 507-643: Tests rely on real environment checks so they can flake
when bd/br CLIs or a .beads folder exist; make tracker availability
deterministic by mocking the detection layer before calling runSetupWizard: stub
the function(s) used to detect beads trackers (e.g., detectBeadsTrackers or any
isCliAvailable/isTrackerInstalled helper and any fs.existsSync check for
".beads") to return "unavailable" for beads, and return available for "json" (or
mock the tracker registry/getAvailableTrackers used by runSetupWizard) so
capturedTrackerChoices always reflect the expected availability in these tests.

In `@src/setup/wizard.ts`:
- Around line 116-118: runSetupWizard currently initializes the detector with an
empty config so detection falls back to process.cwd(); change it to pass the
wizard's options.cwd into tracker setup: thread the cwd from runSetupWizard's
options into detectTrackerPlugins and call instance.initialize({ cwd }) before
detection (and/or call instanceAsDetectable.detect with the cwd if detect
accepts options) so tracker detection uses the intended project directory;
update references to detectTrackerPlugins, instance.initialize, and
instanceAsDetectable.detect to accept and propagate the cwd.
🧹 Nitpick comments (1)
src/config/index.test.ts (1)

715-737: Consider parameterising beads tracker warning tests.

This new beads‑rust case mirrors the beads‑bv warning test; a test.each over beads variants would keep coverage while reducing repetition as more variants are added.

- Make beads epic warning context-aware: TUI mode mentions interactive
  selection, headless mode warns that interactive selection is unavailable
- Restrict formatTrackerUnavailableReason beads heuristics (directory/CLI
  checks) to beads-family trackers only; non-beads trackers get raw errors
- Wrap detectTrackerPlugins per-tracker loop in try/catch/finally so
  detect() errors don't abort the wizard and dispose() always runs
- Thread cwd from runSetupWizard options into detectTrackerPlugins and
  instance.initialize({ workingDir: cwd })
- Mock tracker registry in wizard.test.ts for deterministic detection
  results independent of host environment (bd/br CLIs, .beads dir)
- Add tests for headless beads warning, detect() error handling,
  and non-beads tracker fallback in formatTrackerUnavailableReason

https://claude.ai/code/session_01UrVoS4wbY85XkszHLo2guX
The previous coverage check used only the tests/ batch's "All files"
line, which understates real coverage because bun instruments ALL loaded
source files — not just the ones under test. Files tested in other
batches (wizard.ts, config/index.ts) appeared as ~0% in the tests/
batch, causing the threshold to fail when new code was added to those
files.

Now merges all batch lcov files with lcov before checking the 40%
threshold, giving an accurate picture of aggregate test coverage.

https://claude.ai/code/session_01UrVoS4wbY85XkszHLo2guX
Copy link
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.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @.github/workflows/ci.yml:
- Around line 154-162: Add an explicit guard around the coverage merge step:
check whether any files match the glob coverage-parts/*.lcov before invoking
lcov (using the existing MERGE_ARGS loop), and if none are found either skip the
lcov run or fail with a clear error message so lcov is not invoked with no
--add-tracefile args; also include "empty" in the lcov --ignore-errors list
(i.e., --ignore-errors inconsistent,empty) and remove or avoid the 2>/dev/null
redirection during development so lcov errors are visible.

@codecov
Copy link

codecov bot commented Jan 27, 2026

Codecov Report

❌ Patch coverage is 73.04348% with 31 lines in your changes missing coverage. Please review.
✅ Project coverage is 45.45%. Comparing base (901b027) to head (6e34f53).
⚠️ Report is 6 commits behind head on main.

Files with missing lines Patch % Lines
src/setup/wizard.ts 68.60% 27 Missing ⚠️
src/commands/run.tsx 83.33% 3 Missing ⚠️
src/config/index.ts 90.90% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #232      +/-   ##
==========================================
+ Coverage   45.10%   45.45%   +0.34%     
==========================================
  Files          84       84              
  Lines       24437    24396      -41     
==========================================
+ Hits        11023    11088      +65     
+ Misses      13414    13308     -106     
Files with missing lines Coverage Δ
src/config/index.ts 54.61% <90.90%> (+0.33%) ⬆️
src/commands/run.tsx 10.12% <83.33%> (+1.88%) ⬆️
src/setup/wizard.ts 63.54% <68.60%> (-1.63%) ⬇️

... and 1 file with indirect coverage changes

🚀 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
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.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @.github/workflows/ci.yml:
- Around line 172-175: The printed label "Coverage breakdown by batch (%
Funcs):" does not match the awk extraction (the pipeline grep "^All files"
coverage-output.txt | awk '{print "  " $4}'), which currently pulls the % Stmts
column; fix by either changing the label to "% Stmts" or modifying the awk
parsing to extract the % Funcs value (e.g., split on the '|' delimiter and trim
to the correct field) so the label and extracted column match; update the line
containing the exact strings "Coverage breakdown by batch (% Funcs):" and the
grep/awk pipeline accordingly.

Revert from lcov --summary to bun's text output for the coverage
threshold check. Investigation found that lcov --summary uses raw line
totals (sum of all DA entries across files), while bun's text table uses
per-file average. These produce very different numbers because a handful
of large UI/server files (RunApp.tsx: 2454 lines, server.ts: 1087 lines)
have ~0% coverage and heavily skew the raw total downward.

Per-file average (bun text) treats each source file equally, which
better reflects actual test quality and matches the ~40% threshold the
codebase was calibrated against. lcov files are still uploaded to
Codecov which does its own per-file analysis.

Key changes:
- Use awk to extract % Lines ($6) from bun's text "All files" line
  instead of lcov --summary
- Check the tests/ batch (first "All files" line) which runs 1400+ tests
- Keep threshold at 40% (line coverage, not function coverage)
- Remove lcov install since it's no longer needed for threshold check
- Add empty-value guard for LINES_COV

https://claude.ai/code/session_01UrVoS4wbY85XkszHLo2guX
@subsy subsy force-pushed the claude/improve-beads-detection-uscDL branch from 6207c3a to 6e34f53 Compare January 27, 2026 12:41
@subsy subsy merged commit b0c08d6 into main Jan 27, 2026
9 checks passed
@subsy subsy deleted the claude/improve-beads-detection-uscDL branch January 27, 2026 13:30
sakaman pushed a commit to sakaman/ralph-tui that referenced this pull request Feb 15, 2026
…n-uscDL

Improve beads tracker detection and markdown PRD handling
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.

2 participants

Comments