From c133adb4e05dbe21eb70fbbe4c6c70c5384bd387 Mon Sep 17 00:00:00 2001 From: Ryan Bonial Date: Wed, 28 Jan 2026 15:05:00 -0700 Subject: [PATCH] fix: progress header now displays actual selected feature instead of parsing PRD independently Refactored display_progress_header() to accept feature parameters (id, type, description) instead of calling get_current_feature_info() internally. Moved header display from main() to check_prerequisites() so it shows AFTER feature selection, ensuring the displayed feature matches what will actually be worked on. Co-Authored-By: Claude Sonnet 4.5 --- .ralph/prd.json | 4 +- .ralph/progress.txt | 67 ++++++++++++++++++++++++++++++++ ralph.sh | 52 +++++++++++++++++++++---- tests/ralph-progress-header.bats | 54 ++++++++++++++++++++----- 4 files changed, 157 insertions(+), 20 deletions(-) diff --git a/.ralph/prd.json b/.ralph/prd.json index 2fad56c..3d5c261 100644 --- a/.ralph/prd.json +++ b/.ralph/prd.json @@ -769,8 +769,8 @@ "depends_on": [ "024" ], - "passes": false, - "iterations_taken": 0, + "passes": true, + "iterations_taken": 1, "blocked_reason": null, "test_files": [ "tests/ralph-progress-header.bats" diff --git a/.ralph/progress.txt b/.ralph/progress.txt index eb64b68..4312721 100644 --- a/.ralph/progress.txt +++ b/.ralph/progress.txt @@ -1289,3 +1289,70 @@ Notes for next iteration: - Next available high-priority features: 001 (auto-PR), 018 (spike mode) - Next available features: 001, 002, 005, 006, 016, 018 --- + +--- 2026-01-28 (Feature 028) --- +Feature: 028 - Fix progress header to show correct feature after selection, not from branch name +Status: Completed +Type: bug +Complexity: small + +Implementation: +- Followed TDD Red-Green workflow as required for bug fixes +- RED Phase: Created 5 new tests in tests/ralph-progress-header.bats (tests 214-218) +- RED Phase: Verified tests failed, proving the bug existed: + * get_current_feature_info doesn't sort by priority (unlike get_next_feature_from_prd) + * Header was called in main() BEFORE check_prerequisites (too early) + * Header didn't accept parameters, parsed PRD internally + * Header called get_current_feature_info instead of using selected feature +- Root Cause: Header used different logic than actual feature selection, causing mismatches +- Refactored display_progress_header() to accept parameters: feature_id, feature_type, description + * Added 3 parameter declarations at start of function + * Removed internal call to get_current_feature_info() + * Function now uses passed parameters instead of parsing PRD itself +- Removed display_progress_header() call from main() (line 1877) + * Was being called too early, before feature selection + * Replaced with comment explaining new location +- Added feature selection and header display in check_prerequisites(): + * Protected branch section (lines 808-845): After auto-creating branch based on selected feature + * End of function (lines 891-913): For non-protected branches, selects feature then displays header + * Both locations call get_next_feature_from_prd() and pass results to display_progress_header() + * Used HEADER_DISPLAYED flag to avoid duplicate displays +- Updated 6 old tests in ralph-progress-header.bats to match new behavior: + * Tests 192-194: Increased line offsets to account for new parameter declarations + * Test 196: Changed from checking get_current_feature_info call to checking parameter acceptance + * Tests 204-205: Changed from checking main() to checking check_prerequisites() +- Fixed test syntax: Changed `&& exit 1 || exit 0` to `!` operator for bats compatibility +- GREEN Phase: All 258 tests pass + +Testing: +- ✅ TDD RED: 5 new tests failed before fix (proved bug) +- ✅ TDD GREEN: All 258 tests pass after fix (proved fix works) +- ✅ Bash syntax validation passed: bash -n ralph.sh +- ✅ Test files as specified in PRD: tests/ralph-progress-header.bats updated +- ✅ No quality gates to run (bash-only project, no package.json lint/format/typecheck) + +Key Files Modified: +- ralph.sh: Refactored display_progress_header() (lines 257-332), removed call from main() (line 1877), added feature selection and header calls in check_prerequisites() (lines 808-913) +- tests/ralph-progress-header.bats: Added 5 new tests (214-218), updated 6 old tests (192-196, 204-205) for new behavior +- .ralph/prd.json: Marked feature 028 as complete with iterations_taken=1, test_files verified + +Challenges: +- Initial test failures due to line offset changes after adding parameters +- Test syntax with `&& exit 1 || exit 0` didn't work well with bats, fixed using `!` operator +- Needed to update multiple old tests to match new behavior + +Technical Solution: +- Header now gets feature info explicitly from get_next_feature_from_prd() results +- Feature selection happens ONCE in check_prerequisites, results passed to header +- This ensures header always shows the actual feature that will be worked on +- No more mismatch between header display and actual work + +Notes for next iteration: +- Feature 028 is now complete +- Progress header now correctly shows the selected feature, not a guess from PRD +- Header displays AFTER feature selection, ensuring accuracy +- Both protected and non-protected branch flows handle header display correctly +- Next available critical features: None remaining in critical priority +- Next available high-priority features: 001 (auto-PR), 018 (spike mode) +- Next available features: 001, 002, 005, 006, 016, 018 +--- diff --git a/ralph.sh b/ralph.sh index 9bb7191..d3067e8 100755 --- a/ralph.sh +++ b/ralph.sh @@ -255,6 +255,12 @@ except Exception as e: # Display progress header with current task and stats # Uses terminal control sequences to keep header static at top of screen display_progress_header() { + # Accept feature parameters: feature_id, feature_type, description + # If not provided, will display header without feature info (just stats) + local feature_id="$1" + local feature_type="$2" + local description="$3" + # Only show if enabled and not in quiet mode if [ "$SHOW_PROGRESS_HEADER" != "true" ]; then return @@ -276,11 +282,6 @@ display_progress_header() { stats=$(calculate_prd_stats "$prd_data") IFS=',' read -r total completed blocked remaining <<< "$stats" - # Get current feature info - local current_info - current_info=$(get_current_feature_info "$prd_data") - IFS='|' read -r feature_id feature_type description <<< "$current_info" - # Calculate percentage local percentage=0 if [ "$total" -gt 0 ]; then @@ -807,8 +808,12 @@ check_prerequisites() { local next_feature=$(get_next_feature_from_prd) if [ -n "$next_feature" ]; then + local feature_id=$(echo "$next_feature" | python3 -c "import json,sys; print(json.load(sys.stdin).get('id', 'unknown'))") + local feature_type=$(echo "$next_feature" | python3 -c "import json,sys; print(json.load(sys.stdin).get('type', 'feature'))") local feature_desc=$(echo "$next_feature" | python3 -c "import json,sys; print(json.load(sys.stdin).get('description', ''))") - log_info "Next feature: $feature_desc" + local feature_desc_short=$(echo "$next_feature" | python3 -c "import json,sys; d=json.load(sys.stdin).get('description', ''); print(d[:67] + '...' if len(d) > 70 else d)") + + log_info "Next feature: [$feature_id] $feature_desc" local branch_name=$(generate_branch_name "$next_feature") log_info "Generated branch name: $branch_name" @@ -818,6 +823,11 @@ check_prerequisites() { suggest_feature_branch exit 1 } + + # Display progress header after branch creation (Feature 028) + echo "" + display_progress_header "$feature_id" "$feature_type" "$feature_desc_short" + HEADER_DISPLAYED=true else log_warning "Could not determine next feature from PRD" log_info "Creating generic feature branch..." @@ -826,6 +836,10 @@ check_prerequisites() { suggest_feature_branch exit 1 } + # Display header without feature info + echo "" + display_progress_header "none" "none" "All features complete or blocked" + HEADER_DISPLAYED=true fi fi @@ -887,6 +901,29 @@ check_prerequisites() { git commit -m "Initial commit - Ralph Wiggum setup" fi + # Select next feature and display progress header (Feature 028) + # This ensures header shows the actual feature that will be worked on + # Only do this if header wasn't already displayed in protected branch section + if [ -z "$HEADER_DISPLAYED" ]; then + local next_feature=$(get_next_feature_from_prd) + if [ -n "$next_feature" ]; then + local feature_id=$(echo "$next_feature" | python3 -c "import json,sys; print(json.load(sys.stdin).get('id', 'unknown'))") + local feature_type=$(echo "$next_feature" | python3 -c "import json,sys; print(json.load(sys.stdin).get('type', 'feature'))") + local feature_desc=$(echo "$next_feature" | python3 -c "import json,sys; d=json.load(sys.stdin).get('description', ''); print(d[:67] + '...' if len(d) > 70 else d)") + + log_info "Next feature: [$feature_id] $feature_desc" + echo "" + + # Display progress header with selected feature info + display_progress_header "$feature_id" "$feature_type" "$feature_desc" + else + log_info "No incomplete features found with met dependencies" + echo "" + # Display header without feature info (just stats) + display_progress_header "none" "none" "All features complete or blocked" + fi + fi + log_success "Prerequisites check complete" } @@ -1873,8 +1910,7 @@ main() { echo "╚════════════════════════════════════════╝" echo "" - # Display progress header (Feature 024) - display_progress_header + # Progress header will be displayed in check_prerequisites after feature selection (Feature 028) check_prerequisites run_ralph_loop diff --git a/tests/ralph-progress-header.bats b/tests/ralph-progress-header.bats index 37f8db7..19ccb26 100644 --- a/tests/ralph-progress-header.bats +++ b/tests/ralph-progress-header.bats @@ -59,23 +59,24 @@ } @test "display_progress_header respects SHOW_PROGRESS_HEADER config" { - grep -A5 "display_progress_header()" ralph.sh | grep -q 'if \[ "$SHOW_PROGRESS_HEADER" != "true" \]' + grep -A12 "display_progress_header()" ralph.sh | grep -q 'if \[ "$SHOW_PROGRESS_HEADER" != "true" \]' } @test "display_progress_header respects LOG_LEVEL" { - grep -A10 "display_progress_header()" ralph.sh | grep -q 'if \[ "$LOG_LEVEL" = "ERROR" \]' + grep -A15 "display_progress_header()" ralph.sh | grep -q 'if \[ "$LOG_LEVEL" = "ERROR" \]' } @test "display_progress_header calls get_prd_data" { - grep -A15 "display_progress_header()" ralph.sh | grep -q "get_prd_data" + grep -A20 "display_progress_header()" ralph.sh | grep -q "get_prd_data" } @test "display_progress_header calls calculate_prd_stats" { grep -A25 "display_progress_header()" ralph.sh | grep -q "calculate_prd_stats" } -@test "display_progress_header calls get_current_feature_info" { - grep -A30 "display_progress_header()" ralph.sh | grep -q "get_current_feature_info" +@test "display_progress_header accepts feature parameters" { + # Function should accept feature_id, feature_type, description as parameters + grep -A10 "display_progress_header()" ralph.sh | grep -q 'local feature_id="\$1"' } @test "display_progress_header calculates percentage" { @@ -106,13 +107,14 @@ grep -A70 "display_progress_header()" ralph.sh | grep -q "═══════════════════" } -@test "main function calls display_progress_header" { - awk '/^main\(\)/,/^}/' ralph.sh | grep -q "display_progress_header" +@test "check_prerequisites calls display_progress_header" { + # Header is now called in check_prerequisites after feature selection (Feature 028) + awk '/^check_prerequisites\(\)/,/^}$/' ralph.sh | grep -q "display_progress_header" } -@test "display_progress_header is called before check_prerequisites" { - # Extract main function and verify order - awk '/^main\(\)/,/^}/' ralph.sh | grep -B5 "check_prerequisites" | grep -q "display_progress_header" +@test "display_progress_header is called in check_prerequisites after feature selection" { + # Extract check_prerequisites and verify display_progress_header comes after get_next_feature_from_prd + awk '/^check_prerequisites\(\)/,/^}$/' ralph.sh | grep "get_next_feature_from_prd" -A30 | grep -q "display_progress_header" } @test "display_progress_header handles 'none' when all complete" { @@ -156,3 +158,35 @@ # Code should have a comment explaining the static header technique grep -A80 "display_progress_header()" ralph.sh | grep -iq "static\|persist\|remain" } +# ========================================== +# Tests for Feature 028: Header shows correct selected feature +# ========================================== + +@test "header uses get_next_feature_from_prd for feature selection" { + # Header should rely on get_next_feature_from_prd (which sorts by priority) instead of its own logic + # check_prerequisites should call get_next_feature_from_prd and pass results to header + awk '/^check_prerequisites\(\)/,/^}$/' ralph.sh | grep -q "get_next_feature_from_prd" +} + +@test "display_progress_header is called AFTER feature selection, not before" { + # Header should be displayed after we know which feature will be worked on + # Check that display_progress_header is NOT called before check_prerequisites in main() + ! awk '/^main\(\)/,/^}/' ralph.sh | grep -B5 "check_prerequisites" | grep -q "display_progress_header" +} + +@test "display_progress_header accepts feature parameters instead of parsing PRD" { + # Header should accept explicit feature_id, feature_type, description parameters + # This ensures it displays the SELECTED feature, not its own guess + grep -A5 "^display_progress_header()" ralph.sh | grep -q "local feature_id=\$1\|feature_id=\"\$1\"" +} + +@test "check_prerequisites passes selected feature info to header" { + # After feature selection in check_prerequisites, it should call display_progress_header with feature info + grep -A150 "^check_prerequisites()" ralph.sh | grep "get_next_feature_from_prd" -A30 | grep -q "display_progress_header.*\$" +} + +@test "header no longer calls get_current_feature_info internally" { + # If header accepts parameters, it shouldn't need to call get_current_feature_info + # It should use the passed parameters instead + ! grep -A80 "^display_progress_header()" ralph.sh | grep -v "^#" | grep -q "get_current_feature_info" +}