@@ -478,8 +478,137 @@ prompt_pin_version() {
478478 fi
479479}
480480
481+ # Process a deprecated tool with migration options
482+ process_deprecated_tool () {
483+ local tool=" $1 "
484+
485+ # Determine catalog tool name
486+ local catalog_tool=" $tool "
487+ if [[ " $tool " == * " @" * ]]; then
488+ catalog_tool=" ${tool%%@* } "
489+ fi
490+
491+ # Get tool data
492+ local installed=" $( json_field " $tool " installed) "
493+ local method=" $( json_field " $tool " installed_method) "
494+ local description=" $( catalog_get_property " $catalog_tool " description) "
495+ local superseded_by=" $( catalog_get_superseded_by " $catalog_tool " ) "
496+ local deprecation_msg=" $( catalog_get_deprecation_message " $catalog_tool " ) "
497+
498+ # Get replacement tool info
499+ local replacement_desc=" "
500+ if [ -n " $superseded_by " ] && catalog_has_tool " $superseded_by " ; then
501+ replacement_desc=" $( catalog_get_property " $superseded_by " description) "
502+ fi
503+
504+ printf " \n==> ⚠️ %s %s → DEPRECATED\n" " $tool " " $installed "
505+ [ -n " $description " ] && printf " %s\n" " $description "
506+ [ -n " $deprecation_msg " ] && printf " ⚠️ %s\n" " $deprecation_msg "
507+ if [ -n " $superseded_by " ]; then
508+ printf " Superseded by: %s\n" " $superseded_by "
509+ [ -n " $replacement_desc " ] && printf " └─ %s\n" " $replacement_desc "
510+ fi
511+ printf " installed: %s via %s\n" " $installed " " ${method:- unknown} "
512+
513+ printf " Options:\n"
514+ if [ -n " $superseded_by " ]; then
515+ printf " M = Migrate to %s (recommended)\n" " $superseded_by "
516+ fi
517+ printf " K = Keep %s (no further updates)\n" " $tool "
518+ printf " r = Remove %s\n" " $tool "
519+
520+ local prompt_text
521+ if [ -n " $superseded_by " ]; then
522+ prompt_text=" Action? [M/K/r] "
523+ else
524+ prompt_text=" Action? [K/r] "
525+ fi
526+
527+ local ans=" "
528+ if [ -t 0 ]; then
529+ read -r -p " $prompt_text " ans || true
530+ elif [ -r /dev/tty ]; then
531+ read -r -p " $prompt_text " ans < /dev/tty || true
532+ fi
533+
534+ # Default to K (keep)
535+ [ -z " $ans " ] && ans=" K"
536+
537+ case " $ans " in
538+ [Mm])
539+ if [ -n " $superseded_by " ]; then
540+ printf " Migrating to %s...\n" " $superseded_by "
541+
542+ # Install the replacement
543+ " $ROOT " /scripts/install_tool.sh " $superseded_by " || true
544+
545+ # Re-audit for replacement
546+ CLI_AUDIT_JSON=1 CLI_AUDIT_COLLECT=1 CLI_AUDIT_MERGE=1 " $CLI " audit.py " $superseded_by " > /dev/null 2>&1 || true
547+
548+ # Check if replacement was installed
549+ AUDIT_JSON=" $( cd " $ROOT " && CLI_AUDIT_JSON=1 CLI_AUDIT_RENDER=1 " $CLI " audit.py || true) "
550+ local replacement_installed=" $( json_field " $superseded_by " installed) "
551+
552+ if [ -n " $replacement_installed " ]; then
553+ printf " ✓ %s %s installed\n" " $superseded_by " " $replacement_installed "
554+
555+ # Ask about removing the old tool
556+ printf " Remove deprecated %s? [Y/n] " " $tool "
557+ local remove_ans=" "
558+ if [ -t 0 ]; then
559+ read -r remove_ans || true
560+ elif [ -r /dev/tty ]; then
561+ read -r remove_ans < /dev/tty || true
562+ fi
563+
564+ if [ -z " $remove_ans " ] || [[ " $remove_ans " =~ ^[Yy]$ ]]; then
565+ printf " Removing %s...\n" " $tool "
566+ " $ROOT " /scripts/install_tool.sh " $catalog_tool " uninstall || true
567+ CLI_AUDIT_JSON=1 CLI_AUDIT_COLLECT=1 CLI_AUDIT_MERGE=1 " $CLI " audit.py " $tool " > /dev/null 2>&1 || true
568+ AUDIT_JSON=" $( cd " $ROOT " && CLI_AUDIT_JSON=1 CLI_AUDIT_RENDER=1 " $CLI " audit.py || true) "
569+
570+ local still_installed=" $( json_field " $tool " installed) "
571+ if [ -z " $still_installed " ]; then
572+ printf " ✓ Migration complete: %s → %s\n" " $tool " " $superseded_by "
573+ else
574+ printf " ⚠️ %s may not have been fully removed\n" " $tool "
575+ fi
576+ else
577+ printf " Keeping %s alongside %s\n" " $tool " " $superseded_by "
578+ fi
579+ else
580+ printf " ⚠️ Failed to install %s\n" " $superseded_by "
581+ fi
582+ else
583+ printf " No replacement available, keeping %s\n" " $tool "
584+ fi
585+ ;;
586+ [Kk])
587+ printf " Keeping %s (deprecated, no further updates)\n" " $tool "
588+ ;;
589+ [Rr])
590+ printf " Removing %s...\n" " $tool "
591+ " $ROOT " /scripts/install_tool.sh " $catalog_tool " uninstall || true
592+ CLI_AUDIT_JSON=1 CLI_AUDIT_COLLECT=1 CLI_AUDIT_MERGE=1 " $CLI " audit.py " $tool " > /dev/null 2>&1 || true
593+ AUDIT_JSON=" $( cd " $ROOT " && CLI_AUDIT_JSON=1 CLI_AUDIT_RENDER=1 " $CLI " audit.py || true) "
594+
595+ local still_there=" $( json_field " $tool " installed) "
596+ if [ -z " $still_there " ]; then
597+ printf " ✓ %s has been removed\n" " $tool "
598+ else
599+ printf " ⚠️ %s may not have been fully removed\n" " $tool "
600+ fi
601+ ;;
602+ * )
603+ printf " Keeping %s\n" " $tool "
604+ ;;
605+ esac
606+ }
607+
481608# Build tool list from audit output, grouped by category
482609declare -A CATEGORY_TOOLS
610+ # Track deprecated tools separately (for migration prompts)
611+ DEPRECATED_TOOLS=" "
483612while read -r line; do
484613 [[ " $line " =~ ^state ]] && continue
485614 tool_name=" $( echo " $line " | awk -F' |' ' {gsub(/^ +| +$/,"",$2); print $2}' ) "
@@ -503,6 +632,17 @@ while read -r line; do
503632
504633 # Only process tools with catalog entries (check base tool for multi-version)
505634 if catalog_has_tool " $catalog_name " ; then
635+ # Check if tool is deprecated
636+ if catalog_is_deprecated " $catalog_name " ; then
637+ # Deprecated tool: only track if installed (for migration prompt)
638+ installed=" $( json_field " $tool_name " installed) "
639+ if [ -n " $installed " ]; then
640+ DEPRECATED_TOOLS=" $DEPRECATED_TOOLS $tool_name "
641+ fi
642+ # Skip deprecated tools in main loop (don't suggest installing them)
643+ continue
644+ fi
645+
506646 # Check if tool is pinned (use catalog name for pin check)
507647 # Skip pin checks if IGNORE_PINS=1
508648 if [ " $IGNORE_PINS " != " 1" ]; then
@@ -663,5 +803,46 @@ for category in $(printf '%s\n' "${!CATEGORY_TOOLS[@]}" | while read c; do echo
663803 done
664804done
665805
806+ # Process deprecated tools (if any installed)
807+ DEPRECATED_TOOLS=" $( echo $DEPRECATED_TOOLS | xargs) " # trim whitespace
808+ if [ -n " $DEPRECATED_TOOLS " ]; then
809+ dep_count=$( echo $DEPRECATED_TOOLS | wc -w)
810+
811+ printf " \n"
812+ printf " ================================================================================\n"
813+ printf " ⚠️ Deprecated Tools (%d installed)\n" " $dep_count "
814+ printf " ================================================================================\n"
815+
816+ # Category-level prompt
817+ if [ " ${AUTO_YES_ALL:- } " != " 1" ]; then
818+ printf " Tools: %s\n" " $( echo $DEPRECATED_TOOLS | tr ' ' ' ,' ) "
819+ printf " These tools are no longer maintained and have recommended replacements.\n"
820+ printf " Review deprecated tools? [Y/n] "
821+
822+ dep_ans=" "
823+ if [ -t 0 ]; then
824+ read -r dep_ans || true
825+ elif [ -r /dev/tty ]; then
826+ read -r dep_ans < /dev/tty || true
827+ fi
828+
829+ case " $dep_ans " in
830+ [Nn])
831+ printf " Skipping deprecated tools\n"
832+ ;;
833+ * )
834+ for tool in $DEPRECATED_TOOLS ; do
835+ process_deprecated_tool " $tool "
836+ done
837+ ;;
838+ esac
839+ else
840+ # AUTO_YES_ALL mode - still process deprecated tools
841+ for tool in $DEPRECATED_TOOLS ; do
842+ process_deprecated_tool " $tool "
843+ done
844+ fi
845+ fi
846+
666847echo
667848echo " All done. Re-run: make audit"
0 commit comments