diff --git a/.agents/prompts/build.txt b/.agents/prompts/build.txt index c7d7fbb598..2b9a6639fd 100644 --- a/.agents/prompts/build.txt +++ b/.agents/prompts/build.txt @@ -108,12 +108,14 @@ When referencing specific functions or code include the pattern `file_path:line_ - If webfetch returns 404/403, do NOT retry the same URL or a variation. The URL was likely constructed/guessed. Find an alternative source (gh api, context7, ask the user). - If webfetch returns 429 (rate limited), wait before retrying. Do not make multiple rapid requests to the same domain. # -# 2. markdown-formatter exit codes (6 uses, 100% "failure" rate — expected behavior) -# Root cause: markdown-formatter exits non-zero when it finds lint issues — -# this is expected linter behavior, not a tool failure. -- markdown-formatter exit code 1 means "issues found", not "tool broken". Read the output for the actual findings. -- NEVER retry markdown-formatter expecting a different exit code — fix the reported issues first, then re-run. -- When calling markdown-formatter with action "check" or "lint", expect non-zero exit if the file has issues. +# 2. markdown-formatter exit codes (200x observed — FIXED in t1345) +# Root cause was two bugs: (a) MCP tool exposed actions "lint","check","fix" but +# bash script only handled "format","advanced","cleanup" — unknown actions hit +# default case → exit 1; (b) fix_markdown_file() returned $changes_made (1 when +# changes were made) instead of 0, causing set -e to abort. Both fixed. +# MCP wrapper now captures output on non-zero exit instead of throwing. +- markdown-formatter supports actions: format, fix, lint, check, advanced, cleanup. +- If markdown-formatter still fails, check that .agents/scripts/markdown-formatter.sh exists and is executable. # # 3. read:file_not_found (53x observed) # Root cause: assuming file paths from memory, AGENTS.md references, or prior diff --git a/.agents/scripts/markdown-formatter.sh b/.agents/scripts/markdown-formatter.sh index ea7edf6970..f1efc29bf9 100755 --- a/.agents/scripts/markdown-formatter.sh +++ b/.agents/scripts/markdown-formatter.sh @@ -6,7 +6,7 @@ set -euo pipefail # Automatically fix common Codacy markdown formatting issues # # Usage: ./markdown-formatter.sh [file|directory] -# +# # Common fixes applied: # - Add blank lines around headers # - Add blank lines around code blocks @@ -27,39 +27,40 @@ source "${SCRIPT_DIR}/shared-constants.sh" # Common constants # Print functions print_header() { - local message="$1" - echo -e "${PURPLE}📝 $message${NC}" - return 0 + local message="$1" + echo -e "${PURPLE}📝 $message${NC}" + return 0 } # Fix markdown formatting in a single file fix_markdown_file() { - local file="$1" - local temp_file - temp_file=$(mktemp) - _save_cleanup_scope; trap '_run_cleanups' RETURN - push_cleanup "rm -f '${temp_file}'" - local changes_made=0 - - print_info "Processing: $file" - - # Create backup - cp "$file" "${file}.bak" - - # Apply simple, safe fixes - { - # Remove trailing whitespace - sed 's/[[:space:]]*$//' "$file" | + local file="$1" + local temp_file + temp_file=$(mktemp) + _save_cleanup_scope + trap '_run_cleanups' RETURN + push_cleanup "rm -f '${temp_file}'" + local changes_made=0 + + print_info "Processing: $file" + + # Create backup + cp "$file" "${file}.bak" - # Fix inconsistent list markers (use - for unordered lists) - sed 's/^[[:space:]]*\*[[:space:]]/- /' | - sed 's/^[[:space:]]*+[[:space:]]/- /' | + # Apply simple, safe fixes + { + # Remove trailing whitespace + sed 's/[[:space:]]*$//' "$file" | - # Fix emphasis - use ** for bold, * for italic consistently - sed 's/__\([^_]*\)__/**\1**/g' | # Convert __ to ** + # Fix inconsistent list markers (use - for unordered lists) + sed 's/^[[:space:]]*\*[[:space:]]/- /' | + sed 's/^[[:space:]]*+[[:space:]]/- /' | - # Remove multiple consecutive blank lines (max 2) - awk ' + # Fix emphasis - use ** for bold, * for italic consistently + sed 's/__\([^_]*\)__/**\1**/g' | # Convert __ to ** + + # Remove multiple consecutive blank lines (max 2) + awk ' BEGIN { blank_count = 0 } /^[[:space:]]*$/ { blank_count++ @@ -68,69 +69,72 @@ fix_markdown_file() { } { blank_count = 0; print }' - } > "$temp_file" - - # Check if changes were made - if ! cmp -s "$file" "$temp_file"; then - mv "$temp_file" "$file" - changes_made=1 - print_success "Fixed formatting in: $file" - else - rm "$temp_file" - print_info "No changes needed: $file" - fi - - # Remove backup if no changes were made - if [[ $changes_made -eq 0 ]]; then - rm "${file}.bak" - fi - - return $changes_made - return 0 + } >"$temp_file" + + # Check if changes were made + if ! cmp -s "$file" "$temp_file"; then + mv "$temp_file" "$file" + changes_made=1 + print_success "Fixed formatting in: $file" + else + rm "$temp_file" + print_info "No changes needed: $file" + fi + + # Remove backup if no changes were made + if [[ $changes_made -eq 0 ]]; then + rm "${file}.bak" + fi + + return 0 } # Process directory recursively process_directory() { - local dir="$1" - local total_files=0 - local changed_files=0 - - print_header "Processing markdown files in: $dir" - - # Find all markdown files - while IFS= read -r -d '' file; do - ((total_files++)) || true - if fix_markdown_file "$file"; then - ((changed_files++)) || true - fi - done < <(find "$dir" -name "*.md" -type f -print0) - - echo "" - print_info "Summary: $changed_files/$total_files files modified" - - if [[ $changed_files -gt 0 ]]; then - print_success "Markdown formatting fixes applied successfully" - print_info "Backup files created with .bak extension" - return 0 - else - print_info "No formatting issues found" - return 0 - fi - return 0 + local dir="$1" + local total_files=0 + local changed_files=0 + + print_header "Processing markdown files in: $dir" + + # Find all markdown files + while IFS= read -r -d '' file; do + ((total_files++)) || true + local before_hash after_hash + before_hash=$(sha256sum "$file" | awk '{print $1}') + fix_markdown_file "$file" + after_hash=$(sha256sum "$file" | awk '{print $1}') + if [[ "$before_hash" != "$after_hash" ]]; then + ((changed_files++)) || true + fi + done < <(find "$dir" -name "*.md" -type f -print0) + + echo "" + print_info "Summary: $changed_files/$total_files files modified" + + if [[ $changed_files -gt 0 ]]; then + print_success "Markdown formatting fixes applied successfully" + print_info "Backup files created with .bak extension" + return 0 + else + print_info "No formatting issues found" + return 0 + fi } # Advanced markdown fixes apply_advanced_fixes() { - local file="$1" - local temp_file - temp_file=$(mktemp) - _save_cleanup_scope; trap '_run_cleanups' RETURN - push_cleanup "rm -f '${temp_file}'" + local file="$1" + local temp_file + temp_file=$(mktemp) + _save_cleanup_scope + trap '_run_cleanups' RETURN + push_cleanup "rm -f '${temp_file}'" - print_info "Applying advanced fixes to: $file" + print_info "Applying advanced fixes to: $file" - # Advanced fixes using Python-like logic with awk - awk ' + # Advanced fixes using Python-like logic with awk + awk ' BEGIN { in_code_block = 0 prev_was_header = 0 @@ -182,131 +186,176 @@ apply_advanced_fixes() { # Print the line { print } - ' "$file" > "$temp_file" - - # Replace original if different - if ! cmp -s "$file" "$temp_file"; then - mv "$temp_file" "$file" - print_success "Applied advanced fixes to: $file" - return 0 - else - rm "$temp_file" - return 1 - fi - return 0 + ' "$file" >"$temp_file" + + # Replace original if different + if ! cmp -s "$file" "$temp_file"; then + mv "$temp_file" "$file" + print_success "Applied advanced fixes to: $file" + return 0 + else + rm "$temp_file" + print_info "No advanced fixes needed: $file" + return 0 + fi } # Clean up backup files cleanup_backups() { - local target="${1:-.}" - - print_header "Cleaning up backup files" - - local backup_count - backup_count=$(find "$target" -name "*.md.bak" -type f | wc -l) - - if [[ $backup_count -gt 0 ]]; then - print_info "Found $backup_count backup files" - read -r -p "Remove all .md.bak files? (y/N): " confirm - - if [[ $confirm =~ ^[Yy]$ ]]; then - find "$target" -name "*.md.bak" -type f -delete - print_success "Removed $backup_count backup files" - else - print_info "Backup files preserved" - fi - else - print_info "No backup files found" - fi - return 0 + local target="${1:-.}" + + print_header "Cleaning up backup files" + + local backup_count + backup_count=$(find "$target" -name "*.md.bak" -type f | wc -l) + + if [[ $backup_count -gt 0 ]]; then + print_info "Found $backup_count backup files" + read -r -p "Remove all .md.bak files? (y/N): " confirm + + if [[ $confirm =~ ^[Yy]$ ]]; then + find "$target" -name "*.md.bak" -type f -delete + print_success "Removed $backup_count backup files" + else + print_info "Backup files preserved" + fi + else + print_info "No backup files found" + fi + return 0 } # Show help message show_help() { - print_header "Markdown Formatter Help" - echo "" - echo "Usage: $0 [command] [target]" - echo "" - echo "Commands:" - echo " format [file|dir] - Format markdown files (default)" - echo " advanced [file|dir] - Apply advanced formatting fixes" - echo " cleanup [dir] - Remove backup files" - echo " help - Show this help message" - echo "" - echo "Examples:" - echo " $0 README.md" - echo " $0 format .agents/" - echo " $0 advanced ." - echo " $0 cleanup" - echo "" - echo "Common fixes applied:" - echo " • Add blank lines around headers, code blocks, lists" - echo " • Remove trailing whitespace" - echo " • Fix inconsistent list markers (use -)" - echo " • Normalize emphasis markers (** for bold, * for italic)" - echo " • Add language specifiers to code blocks" - echo " • Fix header spacing" - echo " • Remove excessive blank lines" - echo " • Fix table formatting" - echo " • Fix link and emphasis spacing" - echo "" - echo "Backup files (.bak) are created for all modified files." - return 0 + print_header "Markdown Formatter Help" + echo "" + echo "Usage: $0 [command] [target]" + echo "" + echo "Commands:" + echo " format [file|dir] - Format markdown files (default)" + echo " fix [file|dir] - Alias for format" + echo " lint [file|dir] - Check for issues without modifying files" + echo " check [file|dir] - Alias for lint" + echo " advanced [file|dir] - Apply advanced formatting fixes" + echo " cleanup [dir] - Remove backup files" + echo " help - Show this help message" + echo "" + echo "Examples:" + echo " $0 README.md" + echo " $0 format .agents/" + echo " $0 advanced ." + echo " $0 cleanup" + echo "" + echo "Common fixes applied:" + echo " • Add blank lines around headers, code blocks, lists" + echo " • Remove trailing whitespace" + echo " • Fix inconsistent list markers (use -)" + echo " • Normalize emphasis markers (** for bold, * for italic)" + echo " • Add language specifiers to code blocks" + echo " • Fix header spacing" + echo " • Remove excessive blank lines" + echo " • Fix table formatting" + echo " • Fix link and emphasis spacing" + echo "" + echo "Backup files (.bak) are created for all modified files." + return 0 } # Main function main() { - local _arg1="$1" - local command="${1:-format}" - local target="${2:-.}" - - # Handle case where first argument is a file/directory - if [[ -f "$_arg1" || -d "$_arg1" ]]; then - command="format" - target="$_arg1" - fi - - case "$command" in - "format") - if [[ -f "$target" ]]; then - if [[ "$target" == *.md ]]; then - fix_markdown_file "$target" - else - print_error "File is not a markdown file: $target" - return 1 - fi - elif [[ -d "$target" ]]; then - process_directory "$target" - else - print_error "Target not found: $target" - return 1 - fi - ;; - "advanced") - if [[ -f "$target" && "$target" == *.md ]]; then - apply_advanced_fixes "$target" - elif [[ -d "$target" ]]; then - find "$target" -name "*.md" -type f | while read -r file; do - apply_advanced_fixes "$file" - done - else - print_error "Invalid target for advanced fixes: $target" - return 1 - fi - ;; - "cleanup") - cleanup_backups "$target" - ;; - "help"|"--help"|"-h") - show_help - ;; - *) - print_error "$ERROR_UNKNOWN_COMMAND $command" - show_help - return 1 - ;; - esac - return 0 + local _arg1="${1:-}" + local command="${1:-format}" + local target="${2:-.}" + + # Handle case where first argument is a file/directory + if [[ -f "$_arg1" || -d "$_arg1" ]]; then + command="format" + target="$_arg1" + fi + + case "$command" in + "format" | "fix") + if [[ -f "$target" ]]; then + if [[ "$target" == *.md ]]; then + fix_markdown_file "$target" + else + print_error "File is not a markdown file: $target" + return 1 + fi + elif [[ -d "$target" ]]; then + process_directory "$target" + else + print_error "Target not found: $target" + return 1 + fi + ;; + "lint" | "check") + if [[ -f "$target" ]]; then + if [[ "$target" == *.md ]]; then + # Lint/check mode: report what would change without modifying + local temp_file + temp_file=$(mktemp) + cp "$target" "$temp_file" + fix_markdown_file "$temp_file" + if ! cmp -s "$target" "$temp_file"; then + print_warning "Formatting issues found in: $target" + diff --unified=1 "$target" "$temp_file" || true + else + print_success "No formatting issues: $target" + fi + rm -f "$temp_file" "${temp_file}.bak" + else + print_error "File is not a markdown file: $target" + return 1 + fi + elif [[ -d "$target" ]]; then + local lint_issues=0 + while IFS= read -r -d '' file; do + local temp_file + temp_file=$(mktemp) + cp "$file" "$temp_file" + fix_markdown_file "$temp_file" + if ! cmp -s "$file" "$temp_file"; then + print_warning "Formatting issues found in: $file" + ((lint_issues++)) || true + fi + rm -f "$temp_file" "${temp_file}.bak" + done < <(find "$target" -name "*.md" -type f -print0) + if [[ $lint_issues -gt 0 ]]; then + print_warning "$lint_issues file(s) have formatting issues" + else + print_success "No formatting issues found" + fi + else + print_error "Target not found: $target" + return 1 + fi + ;; + "advanced") + if [[ -f "$target" && "$target" == *.md ]]; then + apply_advanced_fixes "$target" + elif [[ -d "$target" ]]; then + find "$target" -name "*.md" -type f | while read -r file; do + apply_advanced_fixes "$file" + done + else + print_error "Invalid target for advanced fixes: $target" + return 1 + fi + ;; + "cleanup") + cleanup_backups "$target" + ;; + "help" | "--help" | "-h") + show_help + ;; + *) + print_error "$ERROR_UNKNOWN_COMMAND $command" + show_help + return 1 + ;; + esac + return 0 } # Execute main function with all arguments diff --git a/.agents/scripts/markdown-lint-fix.sh b/.agents/scripts/markdown-lint-fix.sh index c055f2b6a7..6718b1170d 100755 --- a/.agents/scripts/markdown-lint-fix.sh +++ b/.agents/scripts/markdown-lint-fix.sh @@ -17,57 +17,55 @@ source "${SCRIPT_DIR}/shared-constants.sh" # Common constants # Print functions print_header() { - local message="$1" - echo -e "${PURPLE}📝 $message${NC}" - return 0 + local message="$1" + echo -e "${PURPLE}📝 $message${NC}" + return 0 } # Check if markdownlint-cli is installed check_markdownlint() { - if command -v markdownlint &> /dev/null; then - return 0 - else - return 1 - fi - return 0 + if command -v markdownlint &>/dev/null; then + return 0 + else + return 1 + fi } # Install markdownlint-cli install_markdownlint() { - print_header "Installing markdownlint-cli" - - if command -v npm &> /dev/null; then - # Use --ignore-scripts to prevent execution of postinstall scripts for security - print_info "Installing markdownlint-cli via npm..." - npm install -g --ignore-scripts markdownlint-cli - - if check_markdownlint; then - print_success "markdownlint-cli installed successfully" - return 0 - else - print_error "Installation failed" - return 1 - fi - else - print_error "npm not found. Please install Node.js and npm first." - print_info "Visit: https://nodejs.org/" - return 1 - fi - return 0 + print_header "Installing markdownlint-cli" + + if command -v npm &>/dev/null; then + # Use --ignore-scripts to prevent execution of postinstall scripts for security + print_info "Installing markdownlint-cli via npm..." + npm install -g --ignore-scripts markdownlint-cli + + if check_markdownlint; then + print_success "markdownlint-cli installed successfully" + return 0 + else + print_error "Installation failed" + return 1 + fi + else + print_error "npm not found. Please install Node.js and npm first." + print_info "Visit: https://nodejs.org/" + return 1 + fi } # Create markdownlint configuration create_markdownlint_config() { - local config_file=".markdownlint.json" - - if [[ -f "$config_file" ]]; then - print_info "markdownlint config already exists: $config_file" - return 0 - fi - - print_info "Creating markdownlint configuration: $config_file" - - cat > "$config_file" << 'EOF' + local config_file=".markdownlint.json" + + if [[ -f "$config_file" ]]; then + print_info "markdownlint config already exists: $config_file" + return 0 + fi + + print_info "Creating markdownlint configuration: $config_file" + + cat >"$config_file" <<'EOF' { "default": true, "MD013": { @@ -82,98 +80,94 @@ create_markdownlint_config() { "MD046": { "style": "fenced" } - return 0 } EOF - - if [[ -f "$config_file" ]]; then - print_success "markdownlint configuration created" - return 0 - else - print_error "Failed to create configuration" - return 1 - fi + + if [[ -f "$config_file" ]]; then + print_success "markdownlint configuration created" + return 0 + else + print_error "Failed to create configuration" + return 1 + fi } # Fix markdown files using markdownlint fix_markdown_with_markdownlint() { - local target="$1" - - print_header "Fixing Markdown Issues with markdownlint" - - # Check if markdownlint is available - if ! check_markdownlint; then - print_warning "markdownlint-cli not found" - read -r -p "Install markdownlint-cli? (y/N): " install_confirm - - if [[ $install_confirm =~ ^[Yy]$ ]]; then - if ! install_markdownlint; then - return 1 - fi - else - print_info "Skipping markdownlint fixes" - return 0 - fi - fi - - # Create config if it doesn't exist - create_markdownlint_config - - # Run markdownlint with fix option - if [[ -f "$target" ]]; then - print_info "Fixing: $target" - markdownlint --fix "$target" - - if markdownlint --fix "$target"; then - print_success "Fixed markdown issues in: $target" - else - print_warning "Some issues may require manual fixing in: $target" - fi - elif [[ -d "$target" ]]; then - print_info "Fixing all markdown files in: $target" - markdownlint --fix "$target/**/*.md" - - if markdownlint --fix "$target"/*.md; then - print_success "Fixed markdown issues in directory: $target" - else - print_warning "Some issues may require manual fixing" - fi - else - print_error "Target not found: $target" - return 1 - fi - - return 0 + local target="$1" + + print_header "Fixing Markdown Issues with markdownlint" + + # Check if markdownlint is available + if ! check_markdownlint; then + print_warning "markdownlint-cli not found" + read -r -p "Install markdownlint-cli? (y/N): " install_confirm + + if [[ $install_confirm =~ ^[Yy]$ ]]; then + if ! install_markdownlint; then + return 1 + fi + else + print_info "Skipping markdownlint fixes" + return 0 + fi + fi + + # Create config if it doesn't exist + create_markdownlint_config + + # Run markdownlint with fix option + if [[ -f "$target" ]]; then + print_info "Fixing: $target" + if markdownlint --fix "$target"; then + print_success "Fixed markdown issues in: $target" + else + print_warning "Some issues may require manual fixing in: $target" + fi + elif [[ -d "$target" ]]; then + print_info "Fixing all markdown files in: $target" + if markdownlint --fix "$target/**/*.md"; then + print_success "Fixed markdown issues in directory: $target" + else + print_warning "Some issues may require manual fixing" + fi + else + print_error "Target not found: $target" + return 1 + fi + + return 0 } # Manual fixes for common Codacy issues apply_manual_fixes() { - local file="$1" - local temp_file - temp_file=$(mktemp) - _save_cleanup_scope; trap '_run_cleanups' RETURN - push_cleanup "rm -f '${temp_file}'" - local changes_made=0 - - print_info "Applying manual fixes to: $file" - - # Create backup - cp "$file" "${file}.bak" - - # Apply manual fixes - { - # Remove trailing whitespace - sed 's/[[:space:]]*$//' "$file" | - - # Fix list markers - use consistent dashes - sed 's/^[[:space:]]*\*[[:space:]]/- /' | - sed 's/^[[:space:]]*+[[:space:]]/- /' | - - # Fix emphasis markers - use ** for bold - sed 's/__\([^_]*\)__/**\1**/g' | - - # Remove excessive blank lines (max 2 consecutive) - awk ' + local file="$1" + local temp_file + temp_file=$(mktemp) + _save_cleanup_scope + trap '_run_cleanups' RETURN + push_cleanup "rm -f '${temp_file}'" + local changes_made=0 + + print_info "Applying manual fixes to: $file" + + # Create backup + cp "$file" "${file}.bak" + + # Apply manual fixes + { + # Remove trailing whitespace + sed 's/[[:space:]]*$//' "$file" | + + # Fix list markers - use consistent dashes + sed 's/^[[:space:]]*\*[[:space:]]/- /' | + sed 's/^[[:space:]]*+[[:space:]]/- /' | + + # Fix emphasis markers - use ** for bold + sed 's/__\([^_]*\)__/**\1**/g' | + + # Remove excessive blank lines (max 2 consecutive) + awk ' BEGIN { blank_count = 0 } /^[[:space:]]*$/ { blank_count++ @@ -181,103 +175,102 @@ apply_manual_fixes() { next } { blank_count = 0; print }' - - } > "$temp_file" - - # Check if changes were made - if ! cmp -s "$file" "$temp_file"; then - mv "$temp_file" "$file" - changes_made=1 - print_success "Applied manual fixes to: $file" - else - rm "$temp_file" - print_info "No manual fixes needed: $file" - fi - - # Remove backup if no changes were made - if [[ $changes_made -eq 0 ]]; then - rm "${file}.bak" - fi - - return $changes_made - return 0 + + } >"$temp_file" + + # Check if changes were made + if ! cmp -s "$file" "$temp_file"; then + mv "$temp_file" "$file" + changes_made=1 + print_success "Applied manual fixes to: $file" + else + rm "$temp_file" + print_info "No manual fixes needed: $file" + fi + + # Remove backup if no changes were made + if [[ $changes_made -eq 0 ]]; then + rm "${file}.bak" + fi + + return 0 } # Show help message show_help() { - print_header "Markdown Lint Fix Help" - echo "" - echo "Usage: $0 [command] [target]" - echo "" - echo "Commands:" - echo " fix [file|dir] - Fix markdown issues (default)" - echo " manual [file|dir] - Apply manual fixes only" - echo " install - Install markdownlint-cli" - echo " config - Create markdownlint configuration" - echo " help - Show this help message" - echo "" - echo "Examples:" - echo " $0 README.md" - echo " $0 fix .agents/" - echo " $0 manual ." - echo " $0 install" - echo "" - echo "This script fixes common Codacy markdown formatting issues:" - echo " • Trailing whitespace" - echo " • Inconsistent list markers" - echo " • Inconsistent emphasis markers" - echo " • Excessive blank lines" - echo " • Line length issues" - echo " • Header formatting" - echo "" - echo "Requires: markdownlint-cli (will offer to install if missing)" - return 0 + print_header "Markdown Lint Fix Help" + echo "" + echo "Usage: $0 [command] [target]" + echo "" + echo "Commands:" + echo " fix [file|dir] - Fix markdown issues (default)" + echo " manual [file|dir] - Apply manual fixes only" + echo " install - Install markdownlint-cli" + echo " config - Create markdownlint configuration" + echo " help - Show this help message" + echo "" + echo "Examples:" + echo " $0 README.md" + echo " $0 fix .agents/" + echo " $0 manual ." + echo " $0 install" + echo "" + echo "This script fixes common Codacy markdown formatting issues:" + echo " • Trailing whitespace" + echo " • Inconsistent list markers" + echo " • Inconsistent emphasis markers" + echo " • Excessive blank lines" + echo " • Line length issues" + echo " • Header formatting" + echo "" + echo "Requires: markdownlint-cli (will offer to install if missing)" + return 0 } # Main function main() { - local _arg1="$1" - local command="${1:-fix}" - local target="${2:-.}" - - # Handle case where first argument is a file/directory - if [[ -f "$_arg1" || -d "$_arg1" ]]; then - command="fix" - target="$_arg1" - fi - - case "$command" in - "fix") - fix_markdown_with_markdownlint "$target" - ;; - "manual") - if [[ -f "$target" && "$target" == *.md ]]; then - apply_manual_fixes "$target" - elif [[ -d "$target" ]]; then - find "$target" -name "*.md" -type f | while read -r file; do - apply_manual_fixes "$file" - done - else - print_error "Invalid target: $target" - return 1 - fi - ;; - "install") - install_markdownlint - ;; - "config") - create_markdownlint_config - ;; - "help"|"--help"|"-h") - show_help - ;; - *) - print_error "$ERROR_UNKNOWN_COMMAND $command" - show_help - return 1 - ;; - esac - return 0 + local _arg1="${1:-}" + local command="${1:-fix}" + local target="${2:-.}" + + # Handle case where first argument is a file/directory + if [[ -f "$_arg1" || -d "$_arg1" ]]; then + command="fix" + target="$_arg1" + fi + + case "$command" in + "fix") + fix_markdown_with_markdownlint "$target" + ;; + "manual") + if [[ -f "$target" && "$target" == *.md ]]; then + apply_manual_fixes "$target" + elif [[ -d "$target" ]]; then + find "$target" -name "*.md" -type f | while read -r file; do + apply_manual_fixes "$file" + done + else + print_error "Invalid target: $target" + return 1 + fi + ;; + "install") + install_markdownlint + ;; + "config") + create_markdownlint_config + ;; + "help" | "--help" | "-h") + show_help + ;; + *) + print_error "$ERROR_UNKNOWN_COMMAND $command" + show_help + return 1 + ;; + esac + return 0 } # Execute main function with all arguments diff --git a/.opencode/tool/markdown-formatter.ts b/.opencode/tool/markdown-formatter.ts index 69a738aaa4..aa6206a37c 100644 --- a/.opencode/tool/markdown-formatter.ts +++ b/.opencode/tool/markdown-formatter.ts @@ -8,7 +8,19 @@ export default tool({ }, async execute(args) { const target = args.target || "." - const result = await Bun.$`bash ${import.meta.dir}/../../.agents/scripts/markdown-formatter.sh ${args.action} ${target}`.text() - return result.trim() + const proc = Bun.spawn( + ["bash", `${import.meta.dir}/../../.agents/scripts/markdown-formatter.sh`, args.action, target], + { stdout: "pipe", stderr: "pipe" }, + ) + const [stdout, stderr] = await Promise.all([ + new Response(proc.stdout).text(), + new Response(proc.stderr).text(), + ]) + await proc.exited + const output = (stdout + (stderr ? "\n" + stderr : "")).trim() + if (proc.exitCode !== 0) { + return `[exit ${proc.exitCode}] ${output}` + } + return output }, }) diff --git a/todo/tasks/t1345-brief.md b/todo/tasks/t1345-brief.md new file mode 100644 index 0000000000..61f89dc496 --- /dev/null +++ b/todo/tasks/t1345-brief.md @@ -0,0 +1,38 @@ +# t1345: Fix markdown-formatter MCP tool -- 100% error rate + +## Session Origin + +Issue #2440, session-miner pulse 2026-02-27 (131 signals, 6/6 failures). + +## What + +Fix the markdown-formatter MCP tool which had a 100% error rate across all uses. + +## Why + +Every agent call to markdown-formatter failed, wasting tool calls and preventing markdown quality checks. The build.txt error prevention guidance was based on an incorrect root cause diagnosis, perpetuating the problem. + +## How + +### Root Cause (three bugs) + +1. **Action mismatch**: MCP tool exposed `["format", "lint", "fix", "check"]` but bash script only handled `["format", "advanced", "cleanup", "help"]`. Actions `lint`, `check`, `fix` hit the `*` default case and returned exit 1. + +2. **Return value bug**: `fix_markdown_file()` returned `$changes_made` (1 when changes were made). With `set -euo pipefail`, returning 1 = failure. Dead `return 0` on next line was unreachable. + +3. **MCP wrapper**: Used `Bun.$\`...\`.text()` which throws `ShellError` on non-zero exit, so agents never saw the output. + +### Files Changed + +- `.agents/scripts/markdown-formatter.sh` -- Added `lint`/`check`/`fix` actions, fixed return value bug +- `.agents/scripts/markdown-lint-fix.sh` -- Fixed same return value bug in `apply_manual_fixes()` +- `.opencode/tool/markdown-formatter.ts` -- Use `Bun.spawn()` to capture output on non-zero exit +- `.agents/prompts/build.txt` -- Updated error prevention section with correct root cause + +## Acceptance Criteria + +- [x] Root cause of 100% failure rate identified (two bugs + wrapper issue) +- [x] All MCP actions (format, fix, lint, check) return exit 0 on success +- [x] ShellCheck zero violations on both scripts +- [x] build.txt updated with correct diagnosis +- [ ] Session miner shows improvement in next pulse (post-merge verification)