diff --git a/.github/workflows/base-check.yml b/.github/workflows/base-check.yml index 4967bc5d..c0b82492 100644 --- a/.github/workflows/base-check.yml +++ b/.github/workflows/base-check.yml @@ -109,7 +109,7 @@ jobs: uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 with: repository: basefoundry/base-cli - ref: 9f3ed25fc0991e3aa9de8411878805c122f90a11 + ref: v0.4.0 path: .base/base-cli - name: Set up Python diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml index 54622ea1..5512a763 100644 --- a/.github/workflows/copilot-setup-steps.yml +++ b/.github/workflows/copilot-setup-steps.yml @@ -29,7 +29,7 @@ jobs: uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 with: repository: basefoundry/base-cli - ref: 9f3ed25fc0991e3aa9de8411878805c122f90a11 + ref: v0.4.0 path: .dependencies/base-cli - name: Set up Python diff --git a/.github/workflows/pylint.yml b/.github/workflows/pylint.yml index e7cfe7d2..2c8ae711 100644 --- a/.github/workflows/pylint.yml +++ b/.github/workflows/pylint.yml @@ -25,7 +25,7 @@ jobs: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 with: repository: basefoundry/base-cli - ref: 9f3ed25fc0991e3aa9de8411878805c122f90a11 + ref: v0.4.0 path: .dependencies/base-cli - name: Set up Python ${{ matrix.python-version }} diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 1be989d1..94251bba 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -31,7 +31,7 @@ jobs: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 with: repository: basefoundry/base-cli - ref: 9f3ed25fc0991e3aa9de8411878805c122f90a11 + ref: v0.4.0 path: .dependencies/base-cli - name: Set up Python @@ -67,13 +67,13 @@ jobs: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 with: repository: basefoundry/base-bash-libs - ref: 2c5ef2c3a9edfbe2cf68d0645be65b920255abff + ref: 9afc98999010d48e8277018b3641e0e796beaf44 path: .dependencies/base-bash-libs - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 with: repository: basefoundry/base-cli - ref: 9f3ed25fc0991e3aa9de8411878805c122f90a11 + ref: v0.4.0 path: .dependencies/base-cli - name: Expose standalone Python package checkout as sibling @@ -119,13 +119,13 @@ jobs: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 with: repository: basefoundry/base-bash-libs - ref: 2c5ef2c3a9edfbe2cf68d0645be65b920255abff + ref: 9afc98999010d48e8277018b3641e0e796beaf44 path: .dependencies/base-bash-libs - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 with: repository: basefoundry/base-cli - ref: 9f3ed25fc0991e3aa9de8411878805c122f90a11 + ref: v0.4.0 path: .dependencies/base-cli - name: Expose standalone Python package checkout as sibling @@ -211,13 +211,13 @@ jobs: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 with: repository: basefoundry/base-bash-libs - ref: 2c5ef2c3a9edfbe2cf68d0645be65b920255abff + ref: 9afc98999010d48e8277018b3641e0e796beaf44 path: .dependencies/base-bash-libs - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 with: repository: basefoundry/base-cli - ref: 9f3ed25fc0991e3aa9de8411878805c122f90a11 + ref: v0.4.0 path: .dependencies/base-cli - name: Expose standalone Python package checkout as sibling @@ -275,13 +275,13 @@ jobs: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 with: repository: basefoundry/base-bash-libs - ref: 2c5ef2c3a9edfbe2cf68d0645be65b920255abff + ref: 9afc98999010d48e8277018b3641e0e796beaf44 path: .dependencies/base-bash-libs - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 with: repository: basefoundry/base-cli - ref: 9f3ed25fc0991e3aa9de8411878805c122f90a11 + ref: v0.4.0 path: .dependencies/base-cli - name: Expose reusable Bash library checkout as sibling @@ -343,7 +343,7 @@ jobs: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 with: repository: basefoundry/base-cli - ref: 9f3ed25fc0991e3aa9de8411878805c122f90a11 + ref: v0.4.0 path: .dependencies/base-cli - name: Set up Python diff --git a/STANDARDS.md b/STANDARDS.md index 38b32e49..05018dfe 100644 --- a/STANDARDS.md +++ b/STANDARDS.md @@ -204,9 +204,9 @@ source-fragment graph. into Base-owned executable shell files. 2. Do not rely on implicit shell exit behavior for control flow. 3. Prefer explicit error handling using helper functions such as: - - `run` - - `exit_if_error` - - `fatal_error` + - `base_std_run` + - `base_std_exit_if_error` + - `base_std_fatal_error` 4. When a command may fail as part of normal flow, handle that failure with `if`, `case`, `||`, or an explicit return-code check. 5. A script should make its error-handling strategy obvious to the reader. diff --git a/base_init.sh b/base_init.sh index 85b3445c..769033bd 100755 --- a/base_init.sh +++ b/base_init.sh @@ -18,18 +18,18 @@ # - export the BASE_* paths that downstream scripts may rely on # - export BASE_OS, BASE_PLATFORM, BASE_HOST_ENV, and BASE_HOST runtime metadata # - resolve and source the reusable Bash standard library -# - require a compatible 1.x base-bash-libs release line +# - require a base-bash-libs release with the v2 `base_` API surface # - add BASE_BIN_DIR to PATH # - provide import_base_lib for convention-based Base Bash library imports # # Downstream scripts should not rediscover Base's directory layout on their own. -# They should use the exported BASE_* variables and import libraries with: +# They should use the exported BASE_* variables and import Base Bash libraries with: # # import_base_lib file/lib_file.sh # -# import_base_lib loads reusable libraries from base-bash-libs. It reports -# missing or invalid libraries through Base stdlib error handling and fails -# immediately, so callers do not need duplicate checks. +# import_base_lib delegates to the v2 package importer. It reports missing or +# invalid libraries through Base stdlib error handling and fails immediately, +# so callers do not need duplicate checks. # [[ -n "${_base_init_sourced:-}" ]] && return 0 @@ -277,6 +277,8 @@ base_init_export_contract() { base_init_source_stdlib() { local stdlib_path="$BASE_BASH_LIBS_DIR/std/lib_std.sh" + local runtime_source + local -a runtime_args=() [[ -f "$stdlib_path" ]] || { base_init_error "Base Bash stdlib '$stdlib_path' was not found." @@ -285,17 +287,29 @@ base_init_source_stdlib() { # shellcheck source=/dev/null source "$stdlib_path" + + runtime_source="${BASE_BASH_LIBS_BOOTSTRAP_SOURCE:-${BASE_BASH_COMMAND_SCRIPT:-$BASE_HOME/base_init.sh}}" + base_init runtime_args --source "$runtime_source" -- "$@" || { + base_init_error "Unable to initialize the base-bash-libs runtime state." + return 1 + } } base_init_require_bash_libs_version() { local loaded_version="${BASE_BASH_LIBS_VERSION:-}" case "$loaded_version" in - 1.*) - base_bash_libs_require_version 1.3.0 + 1.*|2.*) + # The v2 namespace landed before the coordinated v2 release. Keep + # the source checkout usable while the release train is completed; + # the final cutover will raise this floor to 2.0.0. + if ! base_require_version 1.4.0; then + base_init_error "Base requires base-bash-libs 1.4.0 or newer; loaded version is '$loaded_version'." + return 1 + fi ;; *) - base_init_error "Base requires base-bash-libs 1.3.0 or a compatible later 1.x release; loaded version is '$loaded_version'." + base_init_error "Base requires base-bash-libs 1.4.0 or a compatible release with the v2 API; loaded version is '$loaded_version'." return 1 ;; esac @@ -316,21 +330,25 @@ base_init_source_command_protocol() { import_base_lib() { local relative_path="${1:-}" local lib_path + local lib_path - [[ -n "$relative_path" ]] || fatal_error "import_base_lib: no library path provided." - [[ "$relative_path" != /* ]] || fatal_error "import_base_lib: expected a path relative to '$BASE_BASH_LIBS_DIR', got '$relative_path'." + [[ -n "$relative_path" ]] || base_std_fatal_error "import_base_lib: no library path provided." + [[ "$relative_path" != /* ]] || base_std_fatal_error "import_base_lib: expected a path relative to '$BASE_BASH_LIBS_DIR', got '$relative_path'." case "$relative_path" in ..|../*|*/..|*/../*) - fatal_error "import_base_lib: refusing path outside Base Bash library root: '$relative_path'." + base_std_fatal_error "import_base_lib: refusing path outside Base Bash library root: '$relative_path'." ;; - esac + esac lib_path="$BASE_BASH_LIBS_DIR/$relative_path" - [[ -f "$lib_path" ]] || fatal_error "Base reusable library '$relative_path' was not found at '$lib_path'." + [[ -f "$lib_path" ]] || { + base_init_error "Base reusable library '$relative_path' was not found at '$lib_path'." + return 1 + } - # shellcheck source=/dev/null - source "$lib_path" || fatal_error "Failed to import Base library '$lib_path'." + base_std_import "$relative_path" || + base_std_fatal_error "Failed to import Base library '$relative_path'." } base_init_main() { @@ -340,7 +358,7 @@ base_init_main() { base_init_require_bash_libs_version || return 1 base_init_source_command_protocol || return 1 - add_to_path -p "$BASE_BIN_DIR" + base_std_add_to_path -p "$BASE_BIN_DIR" export PATH } diff --git a/bin/base-test b/bin/base-test index b595a2bd..0d392edb 100755 --- a/bin/base-test +++ b/bin/base-test @@ -37,7 +37,7 @@ base_test_unset_env=( -u BASE_BASH_COMMAND_NAME -u BASE_BASH_COMMAND_DIR -u BASE_BASH_COMMAND_SCRIPT - -u BASE_BASH_BOOTSTRAP_SOURCE + -u BASE_BASH_LIBS_BOOTSTRAP_SOURCE -u BASE_INIT_TEST_OS_RELEASE_PATH -u BASE_INIT_TEST_KERNEL_OSRELEASE_PATH -u BASE_INIT_TEST_PROC_VERSION_PATH @@ -51,6 +51,7 @@ base_test_unset_env=( -u BASE_CLI_RUN_ID -u BASE_CLI_RUN_ROOT -u BASE_CLI_PRIMARY_LOG + -u BASE_BASH_LIBS_PRIMARY_LOG -u BASE_CLI_HISTORY_PARENT_RUN_ID -u BASE_CLI_HISTORY_STARTED_AT -u BASE_CLI_HISTORY_SCOPE diff --git a/bin/basectl b/bin/basectl index 606171a8..3dfbd6d2 100755 --- a/bin/basectl +++ b/bin/basectl @@ -260,10 +260,10 @@ basectl_filter_runtime_args() { elif ((parse_options)); then case "$1" in --debug-wrapper) - export LOG_DEBUG=1 + export BASE_BASH_LIBS_LOG_DEBUG=1 ;; --utc-wrapper) - export LOG_UTC=1 + export BASE_BASH_LIBS_LOG_UTC=1 ;; --color) # Propagate the explicit color choice to Python-backed child @@ -300,10 +300,10 @@ basectl_run_bash_script() { export BASE_BASH_COMMAND_SCRIPT="$script_path" # shellcheck disable=SC2034 # Consumed by base_init.sh during this source call. - BASE_BASH_BOOTSTRAP_SOURCE="$script_path" + BASE_BASH_LIBS_BOOTSTRAP_SOURCE="$script_path" # shellcheck source=/dev/null source "$base_home/base_init.sh" "$@" || exit $? - unset BASE_BASH_BOOTSTRAP_SOURCE + unset BASE_BASH_LIBS_BOOTSTRAP_SOURCE readonly BASE_BASH_COMMAND_NAME BASE_BASH_COMMAND_DIR BASE_BASH_COMMAND_SCRIPT unset -f main @@ -312,7 +312,7 @@ basectl_run_bash_script() { source "$script_path" "${basectl_runtime_args[@]}" || exit $? if ! declare -F main >/dev/null 2>&1; then - fatal_error "Script '$script_path' did not define main()." + base_std_fatal_error "Script '$script_path' did not define main()." fi main "${basectl_runtime_args[@]}" diff --git a/cli/bash/commands/basectl/basectl.sh b/cli/bash/commands/basectl/basectl.sh index 5d61eda7..7a34a378 100644 --- a/cli/bash/commands/basectl/basectl.sh +++ b/cli/bash/commands/basectl/basectl.sh @@ -274,13 +274,13 @@ basectl_runtime_base_home() { } basectl_enable_debug_logging() { - set_log_level DEBUG - export LOG_DEBUG=1 + base_std_set_log_level DEBUG + export BASE_BASH_LIBS_LOG_DEBUG=1 } basectl_source_subcommand_module() { local module_name="$1" - local subcommand_script="$__SCRIPT_DIR__/subcommands/${module_name}.sh" + local subcommand_script="$BASE_BASH_COMMANDS_DIR/basectl/subcommands/${module_name}.sh" [[ -f "$subcommand_script" ]] || { basectl_error "Subcommand module '$subcommand_script' was not found." @@ -614,7 +614,7 @@ basectl_initialize_run_bundle() { BASE_CLI_RUN_ID="${BASE_CLI_RUN_ID%%__*}" export BASE_CLI_RUN_ID fi - export BASE_CLI_PRIMARY_LOG="${BASE_CLI_PRIMARY_LOG:-$BASE_CLI_RUN_ROOT/logs/primary.log}" + export BASE_BASH_LIBS_PRIMARY_LOG="${BASE_BASH_LIBS_PRIMARY_LOG:-$BASE_CLI_RUN_ROOT/logs/primary.log}" export BASE_CLI_HISTORY_PARENT_RUN_ID="${BASE_CLI_HISTORY_PARENT_RUN_ID:-$BASE_CLI_RUN_ID}" return 0 fi @@ -631,12 +631,12 @@ basectl_initialize_run_bundle() { export BASE_CLI_RUNTIME_OWNER=base export BASE_CLI_RUN_ID="$run_id" export BASE_CLI_RUN_ROOT="$run_root" - export BASE_CLI_PRIMARY_LOG="$run_root/logs/primary.log" + export BASE_BASH_LIBS_PRIMARY_LOG="$run_root/logs/primary.log" export BASE_CLI_HISTORY_PARENT_RUN_ID="$run_id" printf '{"run_id":"%s","owner":"base","status":"running","started_at":"%s"}\n' \ "$run_id" "$(date -u +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || true)" >"$run_root/run.json" - : >"$BASE_CLI_PRIMARY_LOG" - chmod 600 "$run_root/run.json" "$BASE_CLI_PRIMARY_LOG" || { + : >"$BASE_BASH_LIBS_PRIMARY_LOG" + chmod 600 "$run_root/run.json" "$BASE_BASH_LIBS_PRIMARY_LOG" || { basectl_error "Unable to secure Base run bundle '$run_root'. Check file permissions." return 1 } @@ -653,7 +653,7 @@ basectl_finalize_run_bundle() { "$([[ "$exit_code" == 0 ]] && printf ok || printf error)" "$exit_code" \ "${BASE_CLI_HISTORY_STARTED_AT:-}" \ "$(date -u +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || true)" >"$tmp_file" && mv -f "$tmp_file" "$run_root/run.json" - chmod 600 "$run_root/run.json" "${BASE_CLI_PRIMARY_LOG:-$run_root/logs/primary.log}" || return 1 + chmod 600 "$run_root/run.json" "${BASE_BASH_LIBS_PRIMARY_LOG:-$run_root/logs/primary.log}" || return 1 if [[ "${BASE_CLI_KEEP_TEMP:-}" != true ]]; then rm -rf -- "$run_root/tmp" fi @@ -797,7 +797,7 @@ basectl_main() { BASE_CLI_HISTORY_STARTED_AT="$(date -u +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || true)" export BASE_CLI_HISTORY_STARTED_AT ((base_debug)) && basectl_enable_debug_logging - log_debug "Running basectl command '${command:-}' with args: $*" + base_std_log_debug "Running basectl command '${command:-}' with args: $*" case "$command" in activate) basectl_do_activate "$@"; command_status=$? ;; diff --git a/cli/bash/commands/basectl/subcommands/activate.sh b/cli/bash/commands/basectl/subcommands/activate.sh index 4a2fd6e8..50ddc027 100644 --- a/cli/bash/commands/basectl/subcommands/activate.sh +++ b/cli/bash/commands/basectl/subcommands/activate.sh @@ -24,7 +24,7 @@ EOF base_activate_usage_error() { base_activate_subcommand_usage >&2 - print_error "$*" + base_std_print_error "$*" return 2 } @@ -105,11 +105,11 @@ base_activate_subcommand_main() { } wrapper="$BASE_HOME/bin/base-wrapper" - [[ -x "$wrapper" ]] || fatal_error "Base Python wrapper '$wrapper' is missing or is not executable." + [[ -x "$wrapper" ]] || base_std_fatal_error "Base Python wrapper '$wrapper' is missing or is not executable." resolve_output="$(base_activate_resolve_project "$project" "$wrapper" "${args[@]}")" || return $? base_command_protocol_decode_one project-route "$resolve_output" || { - fatal_error "Unable to resolve project '$project'." + base_std_fatal_error "Unable to resolve project '$project'." } resolved_name="${BASE_COMMAND_PROTOCOL_FIELDS[project_name]}" project_root="${BASE_COMMAND_PROTOCOL_FIELDS[project_root]}" @@ -120,7 +120,7 @@ base_activate_subcommand_main() { base_project_set_history_context "$resolved_name" "$project_root" "$manifest_path" [[ -n "$resolved_name" && -n "$project_root" && -n "$manifest_path" ]] || { - fatal_error "Unable to resolve project '$project'." + base_std_fatal_error "Unable to resolve project '$project'." } base_project_require_manifest_command_trust "$resolved_name" "$manifest_path" "$trust_required" || return $? @@ -128,11 +128,11 @@ base_activate_subcommand_main() { venv_dir="$(base_activate_project_venv_dir "$resolved_name" "$project_root" "$route_venv_dir")" venv_fix="$(base_project_venv_fix "$resolved_name" "$project_root" "$venv_dir" "$uses_uv_manager")" [[ -x "$venv_dir/bin/python" ]] || { - fatal_error "Project virtual environment Python was not found at '$venv_dir/bin/python'. $venv_fix" + base_std_fatal_error "Project virtual environment Python was not found at '$venv_dir/bin/python'. $venv_fix" } shell_rc="$BASE_HOME/lib/bash/runtime/bashrc" - [[ -f "$shell_rc" ]] || fatal_error "Base runtime shell rcfile '$shell_rc' was not found." + [[ -f "$shell_rc" ]] || base_std_fatal_error "Base runtime shell rcfile '$shell_rc' was not found." export BASE_PROJECT="$resolved_name" export BASE_PROJECT_ROOT="$project_root" @@ -141,11 +141,11 @@ base_activate_subcommand_main() { export BASE_HOME if [[ "$preserve_cwd" != "1" ]]; then - cd "$project_root" || fatal_error "Unable to enter project root '$project_root'." + cd "$project_root" || base_std_fatal_error "Unable to enter project root '$project_root'." fi activate_shell="${BASE_ACTIVATE_SHELL:-${BASH:-bash}}" if ! base_activate_shell_is_bash "$activate_shell"; then - fatal_error "basectl activate requires Bash. BASE_ACTIVATE_SHELL='$activate_shell' is not supported. Unset BASE_ACTIVATE_SHELL to use the default Bash runtime shell." + base_std_fatal_error "basectl activate requires Bash. BASE_ACTIVATE_SHELL='$activate_shell' is not supported. Unset BASE_ACTIVATE_SHELL to use the default Bash runtime shell." fi "$activate_shell" --rcfile "$shell_rc" } diff --git a/cli/bash/commands/basectl/subcommands/build.sh b/cli/bash/commands/basectl/subcommands/build.sh index 0d4f4cd1..dce91687 100644 --- a/cli/bash/commands/basectl/subcommands/build.sh +++ b/cli/bash/commands/basectl/subcommands/build.sh @@ -33,7 +33,7 @@ EOF base_build_usage_error() { base_build_subcommand_usage >&2 - print_error "$*" + base_std_print_error "$*" return 2 } @@ -97,7 +97,7 @@ base_build_run_target_record() { environment_prepared=1 fi - log_info "Building target '$target_name' for project '$resolved_name': $display_command" + base_std_log_info "Building target '$target_name' for project '$resolved_name': $display_command" base_validate_command_runner "$command_runner" base_project_run_shell_command "$working_dir" "$command_to_run" basectl-build "${extra_args[@]}" } @@ -113,7 +113,7 @@ base_build_list_targets() { local list_output local printed_header=0 - [[ -x "$wrapper" ]] || fatal_error "Base Python wrapper '$wrapper' is missing or is not executable." + [[ -x "$wrapper" ]] || base_std_fatal_error "Base Python wrapper '$wrapper' is missing or is not executable." if [[ -n "$explicit_project" ]]; then command_args+=(--project "$explicit_project") elif [[ -n "$project" ]]; then @@ -237,13 +237,13 @@ base_build_subcommand_main() { } wrapper="$BASE_HOME/bin/base-wrapper" - [[ -x "$wrapper" ]] || fatal_error "Base Python wrapper '$wrapper' is missing or is not executable." + [[ -x "$wrapper" ]] || base_std_fatal_error "Base Python wrapper '$wrapper' is missing or is not executable." local command_args=(build-targets) [[ -z "$explicit_project" ]] || command_args+=(--project "$explicit_project") command_args+=("${targets[@]}") resolve_output="$("$wrapper" --project base base_projects "${command_args[@]}" "${args[@]}" --format command-protocol)" || return $? - [[ -n "$resolve_output" ]] || fatal_error "Unable to resolve build targets for project '${explicit_project:-current project}'." + [[ -n "$resolve_output" ]] || base_std_fatal_error "Unable to resolve build targets for project '${explicit_project:-current project}'." base_command_protocol_each build-target "$resolve_output" base_build_run_target_record } diff --git a/cli/bash/commands/basectl/subcommands/check.sh b/cli/bash/commands/basectl/subcommands/check.sh index 36e3e863..4a2c1266 100644 --- a/cli/bash/commands/basectl/subcommands/check.sh +++ b/cli/bash/commands/basectl/subcommands/check.sh @@ -83,7 +83,7 @@ EOF } base_check_usage_error() { - print_error "$*" + base_std_print_error "$*" printf "Run 'basectl check --help' for usage.\n" >&2 return 2 } @@ -169,7 +169,7 @@ base_check_subcommand_main() { BASE_SETUP_REMOTE_NETWORK="$remote_network" export BASE_SETUP_PROJECT_NAME export BASE_SETUP_REMOTE_NETWORK - log_debug "Running 'basectl check'." + base_std_log_debug "Running 'basectl check'." if [[ "$output_format" == json ]]; then BASE_SETUP_XCODE_HOMEBREW_DIAGNOSTICS=true setup_run_check_json "$remote_network" else diff --git a/cli/bash/commands/basectl/subcommands/clean.sh b/cli/bash/commands/basectl/subcommands/clean.sh index 67712793..e445785e 100644 --- a/cli/bash/commands/basectl/subcommands/clean.sh +++ b/cli/bash/commands/basectl/subcommands/clean.sh @@ -48,7 +48,7 @@ base_clean_subcommand_main() { fi [[ -n "${2:-}" ]] || { base_clean_subcommand_usage >&2 - print_error "Option '$1' requires an argument." + base_std_print_error "Option '$1' requires an argument." return 2 } args+=("$2") @@ -76,10 +76,10 @@ base_clean_subcommand_main() { if (( ! has_older_than && ! has_keep_last )); then base_clean_subcommand_usage >&2 - print_error "One of '--older-than' or '--keep-last' is required." + base_std_print_error "One of '--older-than' or '--keep-last' is required." return 2 fi - [[ -x "$wrapper" ]] || fatal_error "Base Python wrapper '$wrapper' is missing or is not executable." + [[ -x "$wrapper" ]] || base_std_fatal_error "Base Python wrapper '$wrapper' is missing or is not executable." "$wrapper" --project base base_clean "${args[@]}" } diff --git a/cli/bash/commands/basectl/subcommands/config.sh b/cli/bash/commands/basectl/subcommands/config.sh index 842202f3..c882fc30 100644 --- a/cli/bash/commands/basectl/subcommands/config.sh +++ b/cli/bash/commands/basectl/subcommands/config.sh @@ -80,12 +80,12 @@ base_config_args_request_help() { } base_config_path() { - [[ -n "${HOME:-}" ]] || fatal_error "Environment variable 'HOME' is not set." + [[ -n "${HOME:-}" ]] || base_std_fatal_error "Environment variable 'HOME' is not set." printf '%s\n' "$HOME/.base.d/config.yaml" } base_config_usage_error() { - print_error "$*" + base_std_print_error "$*" printf "Run 'basectl config --help' for usage.\n" >&2 return 2 } @@ -117,7 +117,7 @@ base_config_subcommand_main() { base_config_leaf_usage "$config_command" return $? fi - [[ -x "$wrapper" ]] || fatal_error "Base Python wrapper '$wrapper' is missing or is not executable." + [[ -x "$wrapper" ]] || base_std_fatal_error "Base Python wrapper '$wrapper' is missing or is not executable." BASE_CLI_DISPLAY_COMMAND="basectl config" "$wrapper" --project base base_config "$config_command" "$@" ;; *) diff --git a/cli/bash/commands/basectl/subcommands/demo.sh b/cli/bash/commands/basectl/subcommands/demo.sh index 5b397c01..a1ff0da8 100644 --- a/cli/bash/commands/basectl/subcommands/demo.sh +++ b/cli/bash/commands/basectl/subcommands/demo.sh @@ -27,7 +27,7 @@ EOF base_demo_usage_error() { base_demo_subcommand_usage >&2 - print_error "$*" + base_std_print_error "$*" return 2 } @@ -103,7 +103,7 @@ base_demo_subcommand_main() { } wrapper="$BASE_HOME/bin/base-wrapper" - [[ -x "$wrapper" ]] || fatal_error "Base Python wrapper '$wrapper' is missing or is not executable." + [[ -x "$wrapper" ]] || base_std_fatal_error "Base Python wrapper '$wrapper' is missing or is not executable." if [[ -n "$explicit_project" ]]; then project_args+=(--project "$explicit_project") @@ -112,7 +112,7 @@ base_demo_subcommand_main() { fi resolve_output="$("$wrapper" --project base base_projects demo-script "${project_args[@]}" "${args[@]}" --format command-protocol)" || return $? base_command_protocol_decode_one demo "$resolve_output" || { - fatal_error "Unable to resolve demo script for project '${project:-current project}'." + base_std_fatal_error "Unable to resolve demo script for project '${project:-current project}'." } resolved_name="${BASE_COMMAND_PROTOCOL_FIELDS[project_name]}" project_root="${BASE_COMMAND_PROTOCOL_FIELDS[project_root]}" @@ -125,7 +125,7 @@ base_demo_subcommand_main() { command_runner="${BASE_COMMAND_PROTOCOL_FIELDS[runner]}" [[ -n "$resolved_name" && -n "$project_root" && -n "$manifest_path" && -n "$demo_script" ]] || { - fatal_error "Unable to resolve demo script for project '${project:-current project}'." + base_std_fatal_error "Unable to resolve demo script for project '${project:-current project}'." } command_runner="${command_runner:-}" @@ -143,7 +143,7 @@ base_demo_subcommand_main() { base_project_activate_environment \ "$resolved_name" "$project_root" "$manifest_path" "$dry_run" "$route_venv_dir" "$uses_uv_manager" >/dev/null - log_info "Running demo for project '$resolved_name': $display_command" + base_std_log_info "Running demo for project '$resolved_name': $display_command" if [[ -z "$command_runner" ]]; then (cd "$project_root" && "$demo_script" "${extra_args[@]}") return $? diff --git a/cli/bash/commands/basectl/subcommands/devcontainer.sh b/cli/bash/commands/basectl/subcommands/devcontainer.sh index 689d3997..2c3527ec 100644 --- a/cli/bash/commands/basectl/subcommands/devcontainer.sh +++ b/cli/bash/commands/basectl/subcommands/devcontainer.sh @@ -23,7 +23,7 @@ EOF base_devcontainer_usage_error() { base_devcontainer_subcommand_usage >&2 - print_error "$*" + base_std_print_error "$*" return 2 } @@ -97,17 +97,17 @@ base_devcontainer_subcommand_main() { } wrapper="$BASE_HOME/bin/base-wrapper" - [[ -x "$wrapper" ]] || fatal_error "Base Python wrapper '$wrapper' is missing or is not executable." + [[ -x "$wrapper" ]] || base_std_fatal_error "Base Python wrapper '$wrapper' is missing or is not executable." if [[ -n "$project" ]]; then resolve_output="$("$wrapper" --project base base_projects resolve "$project" "${args[@]}" --format command-protocol)" || return $? base_command_protocol_decode_one project-route "$resolve_output" || { - fatal_error "Unable to resolve project for devcontainer export." + base_std_fatal_error "Unable to resolve project for devcontainer export." } else resolve_output="$("$wrapper" --project base base_projects current --format command-protocol)" || return $? base_command_protocol_decode_one project-reference "$resolve_output" || { - fatal_error "Unable to resolve project for devcontainer export." + base_std_fatal_error "Unable to resolve project for devcontainer export." } fi resolved_name="${BASE_COMMAND_PROTOCOL_FIELDS[project_name]}" @@ -115,7 +115,7 @@ base_devcontainer_subcommand_main() { manifest_path="${BASE_COMMAND_PROTOCOL_FIELDS[manifest_path]}" [[ -n "$resolved_name" && -n "$project_root" && -n "$manifest_path" ]] || { - fatal_error "Unable to resolve project for devcontainer export." + base_std_fatal_error "Unable to resolve project for devcontainer export." } setup_args=(--manifest "$manifest_path" --action devcontainer --format "$output_format") diff --git a/cli/bash/commands/basectl/subcommands/devenv_report.sh b/cli/bash/commands/basectl/subcommands/devenv_report.sh index 183f898e..bda22b3c 100644 --- a/cli/bash/commands/basectl/subcommands/devenv_report.sh +++ b/cli/bash/commands/basectl/subcommands/devenv_report.sh @@ -21,7 +21,7 @@ EOF base_devenv_report_usage_error() { base_devenv_report_subcommand_usage >&2 - print_error "$*" + base_std_print_error "$*" return 2 } @@ -91,17 +91,17 @@ base_devenv_report_subcommand_main() { } wrapper="$BASE_HOME/bin/base-wrapper" - [[ -x "$wrapper" ]] || fatal_error "Base Python wrapper '$wrapper' is missing or is not executable." + [[ -x "$wrapper" ]] || base_std_fatal_error "Base Python wrapper '$wrapper' is missing or is not executable." if [[ -n "$project" ]]; then resolve_output="$("$wrapper" --project base base_projects resolve "$project" "${args[@]}" --format command-protocol)" || return $? base_command_protocol_decode_one project-route "$resolve_output" || { - fatal_error "Unable to resolve project for devenv-report." + base_std_fatal_error "Unable to resolve project for devenv-report." } else resolve_output="$("$wrapper" --project base base_projects current --format command-protocol)" || return $? base_command_protocol_decode_one project-reference "$resolve_output" || { - fatal_error "Unable to resolve project for devenv-report." + base_std_fatal_error "Unable to resolve project for devenv-report." } fi resolved_name="${BASE_COMMAND_PROTOCOL_FIELDS[project_name]}" @@ -109,7 +109,7 @@ base_devenv_report_subcommand_main() { manifest_path="${BASE_COMMAND_PROTOCOL_FIELDS[manifest_path]}" [[ -n "$resolved_name" && -n "$project_root" && -n "$manifest_path" ]] || { - fatal_error "Unable to resolve project for devenv-report." + base_std_fatal_error "Unable to resolve project for devenv-report." } setup_args=(--manifest "$manifest_path" --action devenv-report --format "$output_format" "$resolved_name") diff --git a/cli/bash/commands/basectl/subcommands/docs.sh b/cli/bash/commands/basectl/subcommands/docs.sh index 7edf2896..2ee47e5f 100644 --- a/cli/bash/commands/basectl/subcommands/docs.sh +++ b/cli/bash/commands/basectl/subcommands/docs.sh @@ -21,7 +21,7 @@ EOF base_docs_usage_error() { base_docs_subcommand_usage >&2 - print_error "$*" + base_std_print_error "$*" return 2 } @@ -42,7 +42,7 @@ base_docs_open_url() { local opener if ! opener="$(base_docs_platform_opener)"; then - print_error "No supported browser opener was found. Use 'basectl docs --show-url' to print the URL." + base_std_print_error "No supported browser opener was found. Use 'basectl docs --show-url' to print the URL." return 1 fi diff --git a/cli/bash/commands/basectl/subcommands/doctor.sh b/cli/bash/commands/basectl/subcommands/doctor.sh index 10774e42..d5a4099a 100644 --- a/cli/bash/commands/basectl/subcommands/doctor.sh +++ b/cli/bash/commands/basectl/subcommands/doctor.sh @@ -42,7 +42,7 @@ EOF } base_doctor_usage_error() { - print_error "$*" + base_std_print_error "$*" printf "Run 'basectl doctor --help' for usage.\n" >&2 return 2 } @@ -62,7 +62,7 @@ EOF } base_doctor_explain_usage_error() { - print_error "$*" + base_std_print_error "$*" printf "Run 'basectl doctor explain --help' for usage.\n" >&2 return 2 } @@ -73,7 +73,7 @@ base_doctor_explain_finding() { local python_bin python_bin="$(setup_diagnostics_python_bin)" || - fatal_error "Python is required to render Base finding explanations." + base_std_fatal_error "Python is required to render Base finding explanations." setup_ensure_cached_paths env BASE_HOME="$BASE_HOME" PYTHONPATH="$_BASE_SETUP_PYTHONPATH_CACHE" \ "$python_bin" -m base_setup.finding_explanations "$finding_id" --format "$output_format" @@ -169,12 +169,12 @@ base_doctor_print_collected_check_results() { count="${#_BASE_SETUP_CHECK_NAMES[@]}" if ((count > 0)); then metadata_output="$(setup_base_check_metadata "${_BASE_SETUP_CHECK_NAMES[@]}")" || - fatal_error "Base diagnostic metadata renderer failed." + base_std_fatal_error "Base diagnostic metadata renderer failed." while IFS= read -r metadata_line; do metadata_lines+=("$metadata_line") done <<<"$metadata_output" if ((${#metadata_lines[@]} != count)); then - fatal_error "Base diagnostic metadata renderer returned ${#metadata_lines[@]} rows for $count checks." + base_std_fatal_error "Base diagnostic metadata renderer returned ${#metadata_lines[@]} rows for $count checks." fi fi @@ -183,10 +183,10 @@ base_doctor_print_collected_check_results() { fix="$(setup_check_result_recovery "$i")" IFS=$'\t' read -r metadata_name finding_id display_name <<<"${metadata_lines[$i]}" if [[ "$metadata_name" != "${_BASE_SETUP_CHECK_NAMES[$i]}" || -z "$finding_id" || -z "$display_name" ]]; then - fatal_error "Base diagnostic metadata renderer returned invalid metadata for '${_BASE_SETUP_CHECK_NAMES[$i]}'." + base_std_fatal_error "Base diagnostic metadata renderer returned invalid metadata for '${_BASE_SETUP_CHECK_NAMES[$i]}'." fi if [[ "$status" == ok && -n "${_BASE_SETUP_CHECK_DEBUG_MESSAGES[$i]}" ]]; then - log_debug "${_BASE_SETUP_CHECK_DEBUG_MESSAGES[$i]}" + base_std_log_debug "${_BASE_SETUP_CHECK_DEBUG_MESSAGES[$i]}" fi if [[ "$status" == ok ]]; then fix="" @@ -229,17 +229,17 @@ base_doctor_run_ci_runtime_text() { if ((errors == 0)); then if [[ -n "$project" ]]; then - log_info "Base CI doctor found no blocking issues for project '$project'." + base_std_log_info "Base CI doctor found no blocking issues for project '$project'." else - log_info 'Base CI doctor found no blocking issues.' + base_std_log_info 'Base CI doctor found no blocking issues.' fi return 0 fi if [[ -n "$project" ]]; then - log_info "Base CI doctor found $errors blocking issue(s) for project '$project'." + base_std_log_info "Base CI doctor found $errors blocking issue(s) for project '$project'." else - log_info "Base CI doctor found $errors blocking issue(s)." + base_std_log_info "Base CI doctor found $errors blocking issue(s)." fi return 1 } @@ -254,8 +254,8 @@ base_doctor_run_json() { local remote_network="${2:-${BASE_SETUP_REMOTE_NETWORK:-}}" BASE_SETUP_XCODE_HOMEBREW_DIAGNOSTICS=true setup_collect_base_check_results warn || true - std_make_temp_dir check_result_dir base-doctor-json || - fatal_error "Unable to create temporary Base doctor JSON result directory." + base_std_make_temp_dir check_result_dir base-doctor-json || + base_std_fatal_error "Unable to create temporary Base doctor JSON result directory." if setup_profiles_enabled; then if ! profile_json="$(setup_run_base_dev_layer doctor --format json)"; then @@ -386,7 +386,7 @@ base_doctor_subcommand_main() { BASE_SETUP_REMOTE_NETWORK="$remote_network" export BASE_SETUP_PROJECT_NAME export BASE_SETUP_REMOTE_NETWORK - log_debug "Running 'basectl doctor'." + base_std_log_debug "Running 'basectl doctor'." if setup_ci_runtime_only; then if [[ "$output_format" == json ]]; then base_doctor_run_json "$project" "$remote_network" @@ -419,17 +419,17 @@ base_doctor_subcommand_main() { if ((errors == 0)); then if [[ -n "$project" ]]; then - log_info "Base doctor found no blocking issues for project '$project'." + base_std_log_info "Base doctor found no blocking issues for project '$project'." else - log_info 'Base doctor found no blocking issues.' + base_std_log_info 'Base doctor found no blocking issues.' fi return 0 fi if [[ -n "$project" ]]; then - log_info "Base doctor found $errors blocking issue(s) for project '$project'." + base_std_log_info "Base doctor found $errors blocking issue(s) for project '$project'." else - log_info "Base doctor found $errors blocking issue(s)." + base_std_log_info "Base doctor found $errors blocking issue(s)." fi return 1 } diff --git a/cli/bash/commands/basectl/subcommands/export_context.sh b/cli/bash/commands/basectl/subcommands/export_context.sh index f5254e1b..3cd2e3ac 100644 --- a/cli/bash/commands/basectl/subcommands/export_context.sh +++ b/cli/bash/commands/basectl/subcommands/export_context.sh @@ -27,7 +27,7 @@ EOF base_export_context_usage_error() { base_export_context_subcommand_usage >&2 - print_error "$*" + base_std_print_error "$*" return 2 } @@ -57,7 +57,7 @@ base_export_context_subcommand_main() { esac done - if ! arg_parse parsed_options positionals option_specs -- "$@"; then + if ! base_arg_parse parsed_options positionals option_specs -- "$@"; then base_export_context_subcommand_usage >&2 return 2 fi @@ -110,17 +110,17 @@ base_export_context_subcommand_main() { } wrapper="$BASE_HOME/bin/base-wrapper" - [[ -x "$wrapper" ]] || fatal_error "Base Python wrapper '$wrapper' is missing or is not executable." + [[ -x "$wrapper" ]] || base_std_fatal_error "Base Python wrapper '$wrapper' is missing or is not executable." if [[ -n "$project" ]]; then resolve_output="$("$wrapper" --project base base_projects resolve "$project" "${resolve_args[@]}" --format command-protocol)" || return $? base_command_protocol_decode_one project-route "$resolve_output" || { - fatal_error "Unable to resolve project for export-context." + base_std_fatal_error "Unable to resolve project for export-context." } else resolve_output="$("$wrapper" --project base base_projects current --format command-protocol)" || return $? base_command_protocol_decode_one project-reference "$resolve_output" || { - fatal_error "Unable to resolve project for export-context." + base_std_fatal_error "Unable to resolve project for export-context." } fi resolved_name="${BASE_COMMAND_PROTOCOL_FIELDS[project_name]}" @@ -129,7 +129,7 @@ base_export_context_subcommand_main() { base_project_set_history_context "$resolved_name" "$project_root" "$manifest_path" [[ -n "$resolved_name" && -n "$project_root" && -n "$manifest_path" ]] || { - fatal_error "Unable to resolve project for export-context." + base_std_fatal_error "Unable to resolve project for export-context." } exporter_args+=( diff --git a/cli/bash/commands/basectl/subcommands/gh.sh b/cli/bash/commands/basectl/subcommands/gh.sh index d93be862..e86f3c13 100644 --- a/cli/bash/commands/basectl/subcommands/gh.sh +++ b/cli/bash/commands/basectl/subcommands/gh.sh @@ -134,7 +134,7 @@ base_gh_auth_environment_warning() { local token_name token_name="$(base_gh_auth_environment_token_name "$hostname")" || return 1 - log_warn "GitHub CLI is using $token_name from the environment. Stored credentials and 'basectl gh auth refresh' will not affect commands until this variable is unset or rotated at its source." + base_std_log_warn "GitHub CLI is using $token_name from the environment. Stored credentials and 'basectl gh auth refresh' will not affect commands until this variable is unset or rotated at its source." return 0 } @@ -150,9 +150,9 @@ base_gh_auth_status() { ((status == 0)) && return 0 if grep -Eqi 'lookup .*api\.[^[:space:]]+|error connecting|no such host|network' <<<"$output"; then - log_warn "Unable to reach GitHub while checking authentication. Verify network or DNS and retry." + base_std_log_warn "Unable to reach GitHub while checking authentication. Verify network or DNS and retry." elif grep -Eqi 'not logged in|invalid|failed to log in|bad credentials|401' <<<"$output"; then - log_warn "GitHub authentication is unavailable for '$hostname'. Run 'gh auth login -h $hostname'." + base_std_log_warn "GitHub authentication is unavailable for '$hostname'. Run 'gh auth login -h $hostname'." fi return "$status" @@ -242,7 +242,7 @@ base_gh_auth_refresh_command() { token_name="$(base_gh_auth_environment_token_name "$hostname")" || true if [[ -n "$token_name" ]]; then base_gh_error "Cannot refresh the stored GitHub credential while $token_name is set." - log_warn "Unset $token_name for this process or rotate the environment token at its source, then retry." + base_std_log_warn "Unset $token_name for this process or rotate the environment token at its source, then retry." return 2 fi @@ -250,7 +250,7 @@ base_gh_auth_refresh_command() { args=(auth refresh --hostname "$hostname") [[ -z "$scopes_csv" ]] || args+=(--scopes "$scopes_csv") ((clipboard)) && args+=(--clipboard) - base_gh_run "${args[@]}" || status=$? + base_cli_gh_run "${args[@]}" || status=$? ((status == 0)) || return "$status" printf "GitHub credentials refreshed for '%s'.\n" "$hostname" } @@ -615,7 +615,7 @@ EOF } base_gh_error() { - print_error "$*" + base_std_print_error "$*" } base_gh_usage_error() { @@ -631,7 +631,7 @@ base_gh_require_command() { local command="$1" if [[ "$command" == "gh" ]]; then - gh_require_cli + base_gh_require_cli return $? fi @@ -641,32 +641,27 @@ base_gh_require_command() { } } -base_gh_auth_status_diagnostics() { - gh_auth_status_diagnostics -} - -base_gh_report_command_failure() { - local status="$1" - shift - - gh_report_command_failure "$status" "$@" -} - base_gh_run() { local status=0 - gh_run "$@" || status=$? + base_gh_require_cli || return 1 + gh "$@" || status=$? ((status == 0)) && return 0 + base_gh_report_command_failure "$status" "$@" || true base_gh_auth_environment_warning github.com || true if [[ "${1:-}" == project ]]; then - log_warn "GitHub Project operations require the 'project' scope for stored OAuth credentials." - log_warn "Run 'basectl gh auth refresh --scope project' if the stored credential is active." + base_std_log_warn "GitHub Project operations require the 'project' scope for stored OAuth credentials." + base_std_log_warn "Run 'basectl gh auth refresh --scope project' if the stored credential is active." fi return "$status" } +base_cli_gh_run() { + base_gh_run "$@" +} + base_gh_args_request_help() { local arg @@ -690,7 +685,7 @@ base_gh_default_branch() { local base_default_branch repo_root repo_root="$(git rev-parse --show-toplevel 2>/dev/null || printf '.')" - if git_detect_default_branch "$repo_root" base_default_branch; then + if base_git_detect_default_branch "$repo_root" base_default_branch; then printf '%s\n' "$base_default_branch" return 0 fi @@ -865,7 +860,7 @@ base_gh_issue_readiness_project_row() { repo_literal="$(base_gh_jq_string_literal "$repo")" query=".items[] | select((.content.number == $issue) and (.content.repository == $repo_literal)) | [.status // \"\", .priority // \"\", .size // \"\", .area // \"\", .initiative // \"\"] | join(\"\u001f\")" - base_gh_run project item-list "$project_number" --owner "$project_owner" --format json --limit 1000 --jq "$query" + base_cli_gh_run project item-list "$project_number" --owner "$project_owner" --format json --limit 1000 --jq "$query" } base_gh_issue_readiness_format_error() { @@ -999,19 +994,19 @@ base_gh_issue_readiness() { return $? } - body="$(base_gh_run issue view "$issue" --repo "$github_repo" --json body --jq .body)" + body="$(base_cli_gh_run issue view "$issue" --repo "$github_repo" --json body --jq .body)" status=$? ((status == 0)) || { base_gh_issue_readiness_upstream_error "$output_format" issue_view_body "$status" return $? } - labels_output="$(base_gh_run issue view "$issue" --repo "$github_repo" --json labels --jq '.labels[].name')" + labels_output="$(base_cli_gh_run issue view "$issue" --repo "$github_repo" --json labels --jq '.labels[].name')" status=$? ((status == 0)) || { base_gh_issue_readiness_upstream_error "$output_format" issue_view_labels "$status" return $? } - assignees_output="$(base_gh_run issue view "$issue" --repo "$github_repo" --json assignees --jq '.assignees[].login')" + assignees_output="$(base_cli_gh_run issue view "$issue" --repo "$github_repo" --json assignees --jq '.assignees[].login')" status=$? ((status == 0)) || { base_gh_issue_readiness_upstream_error "$output_format" issue_view_assignees "$status" @@ -1171,7 +1166,7 @@ base_gh_infer_github_repo() { local github_repo repo_root repo_root="$(git rev-parse --show-toplevel 2>/dev/null || printf '.')" - gh_infer_repo_from_origin "$repo_root" github_repo || return 1 + base_gh_infer_repo_from_origin "$repo_root" github_repo || return 1 printf '%s\n' "$github_repo" } @@ -1290,10 +1285,10 @@ base_gh_issue_default_assignee_from_config() { base_gh_join_csv() { local joined="" - # shellcheck disable=SC2034 # Passed by name to str_join. + # shellcheck disable=SC2034 # Passed by name to base_str_join. local values=("$@") - str_join joined ", " values + base_str_join joined ", " values printf '%s\n' "$joined" } @@ -1353,11 +1348,11 @@ base_gh_apply_project_issue_fields() { if [[ -n "$output" ]]; then while IFS= read -r line || [[ -n "$line" ]]; do - [[ -n "$line" ]] && log_warn "$line" + [[ -n "$line" ]] && base_std_log_warn "$line" done <<<"$output" fi - log_warn "Project field update failed. Set fields manually or rerun:" - log_warn "$(base_gh_project_issue_set_fields_command "$@")" + base_std_log_warn "Project field update failed. Set fields manually or rerun:" + base_std_log_warn "$(base_gh_project_issue_set_fields_command "$@")" return "$status" } @@ -1419,7 +1414,7 @@ base_gh_do_issue() { base_gh_issue_list_usage return 0 fi - base_gh_run issue list "$@" + base_cli_gh_run issue list "$@" ;; create) if base_gh_args_request_help "$@"; then @@ -1570,7 +1565,7 @@ base_gh_issue_create() { if [[ -n "$github_repo" ]]; then issue_args+=(--repo "$github_repo") fi - issue_output="$(base_gh_run "${issue_args[@]}")" || return $? + issue_output="$(base_cli_gh_run "${issue_args[@]}")" || return $? printf '%s\n' "$issue_output" if ((configure_project)) && [[ -n "$github_repo" ]]; then @@ -1663,19 +1658,19 @@ base_gh_pr_create() { return 2 fi if [[ -n "$issue" && "$no_fixes" -eq 0 ]]; then - std_make_temp_file body_file basectl-gh-pr || return 1 + base_std_make_temp_file body_file basectl-gh-pr || return 1 base_gh_pr_policy_body "$issue" "$github_repo" > "$body_file" || { status=$? rm -f "$body_file" return "$status" } printf 'Auto-linking PR to issue #%s from branch name. Pass --no-fixes to suppress.\n' "$issue" - base_gh_run pr create --fill --body-file "$body_file" "${passthrough[@]}" + base_cli_gh_run pr create --fill --body-file "$body_file" "${passthrough[@]}" status=$? rm -f "$body_file" return "$status" fi - base_gh_run pr create --fill "${passthrough[@]}" + base_cli_gh_run pr create --fill "${passthrough[@]}" } base_gh_issue_start() { @@ -1794,28 +1789,28 @@ base_gh_do_pr() { base_gh_pr_leaf_usage status return 0 fi - base_gh_run pr status "$@" + base_cli_gh_run pr status "$@" ;; checks) if base_gh_args_request_help "$@"; then base_gh_pr_leaf_usage checks return 0 fi - base_gh_run pr checks "$@" + base_cli_gh_run pr checks "$@" ;; ready) if base_gh_args_request_help "$@"; then base_gh_pr_leaf_usage ready return 0 fi - base_gh_run pr ready "$@" + base_cli_gh_run pr ready "$@" ;; merge) if base_gh_args_request_help "$@"; then base_gh_pr_leaf_usage merge return 0 fi - base_gh_run pr merge "$@" + base_cli_gh_run pr merge "$@" ;; -h|--help|help|"") base_gh_pr_usage diff --git a/cli/bash/commands/basectl/subcommands/gh_branch_worktree.sh b/cli/bash/commands/basectl/subcommands/gh_branch_worktree.sh index 4cda5445..77e90027 100644 --- a/cli/bash/commands/basectl/subcommands/gh_branch_worktree.sh +++ b/cli/bash/commands/basectl/subcommands/gh_branch_worktree.sh @@ -155,20 +155,20 @@ base_gh_format_unix_date() { base_gh_worktree_path_for_branch() { local branch="$1" - git_worktree_path_for_branch "$branch" + base_git_worktree_path_for_branch "$branch" } base_gh_branch_upstream() { local branch="$1" - git_branch_upstream . "$branch" + base_git_branch_upstream . "$branch" } base_gh_branch_merged_to_ref() { local branch="$1" local ref="$2" - git_branch_merged_to_ref . "$branch" "$ref" + base_git_branch_merged_to_ref . "$branch" "$ref" } base_gh_prune_github_ready() { @@ -190,7 +190,7 @@ base_gh_branch_github_merged() { base_gh_error "GitHub merge verification requires the GitHub CLI 'gh' on PATH." return 2 fi - count="$(base_gh_run pr list --head "$branch" --state merged --json number --jq 'length')" || return 2 + count="$(base_cli_gh_run pr list --head "$branch" --state merged --json number --jq 'length')" || return 2 if [[ ! "$count" =~ ^[0-9]+$ ]]; then base_gh_error "GitHub merge verification returned an invalid result for branch '$branch'." return 2 @@ -234,7 +234,7 @@ base_gh_branch_delete() { } base_gh_list_remote_branches() { - git_list_remote_branches . + base_git_list_remote_branches . } base_gh_branch_delete_remote() { @@ -501,7 +501,7 @@ base_gh_resolve_physical_path() { } base_gh_list_worktree_branches() { - git_list_worktree_branches . + base_git_list_worktree_branches . } base_gh_worktree_dirty() { diff --git a/cli/bash/commands/basectl/subcommands/history.sh b/cli/bash/commands/basectl/subcommands/history.sh index e92d4d2f..39cef7b8 100644 --- a/cli/bash/commands/basectl/subcommands/history.sh +++ b/cli/bash/commands/basectl/subcommands/history.sh @@ -58,7 +58,7 @@ base_history_subcommand_main() { --project|--command|--status|--limit|--format|--last|--since|--until) [[ -n "${2:-}" ]] || { base_history_subcommand_usage >&2 - print_error "Option '$1' requires an argument." + base_std_print_error "Option '$1' requires an argument." return 2 } args+=("$1" "$2") @@ -75,6 +75,6 @@ base_history_subcommand_main() { esac done - [[ -x "$wrapper" ]] || fatal_error "Base Python wrapper '$wrapper' is missing or is not executable." + [[ -x "$wrapper" ]] || base_std_fatal_error "Base Python wrapper '$wrapper' is missing or is not executable." BASE_CLI_DISPLAY_COMMAND="basectl history" "$wrapper" --project base base_history "${args[@]}" } diff --git a/cli/bash/commands/basectl/subcommands/logs.sh b/cli/bash/commands/basectl/subcommands/logs.sh index 08c1b309..006f5012 100644 --- a/cli/bash/commands/basectl/subcommands/logs.sh +++ b/cli/bash/commands/basectl/subcommands/logs.sh @@ -122,7 +122,7 @@ base_logs_subcommand_main() { ;; unknown:*) base_logs_subcommand_usage >&2 - print_error "Unknown logs command '${help_target#unknown:}'. Supported commands: last-failed." + base_std_print_error "Unknown logs command '${help_target#unknown:}'. Supported commands: last-failed." return 2 ;; esac @@ -141,7 +141,7 @@ base_logs_subcommand_main() { --command|--limit|--lines|--format) [[ -n "${2:-}" ]] || { base_logs_subcommand_usage >&2 - print_error "Option '$1' requires an argument." + base_std_print_error "Option '$1' requires an argument." return 2 } args+=("$1" "$2") @@ -158,6 +158,6 @@ base_logs_subcommand_main() { esac done - [[ -x "$wrapper" ]] || fatal_error "Base Python wrapper '$wrapper' is missing or is not executable." + [[ -x "$wrapper" ]] || base_std_fatal_error "Base Python wrapper '$wrapper' is missing or is not executable." BASE_CLI_DISPLAY_COMMAND="basectl logs" "$wrapper" --project base base_logs "${args[@]}" } diff --git a/cli/bash/commands/basectl/subcommands/onboard.sh b/cli/bash/commands/basectl/subcommands/onboard.sh index 6e897dfe..a7d0121d 100644 --- a/cli/bash/commands/basectl/subcommands/onboard.sh +++ b/cli/bash/commands/basectl/subcommands/onboard.sh @@ -31,7 +31,7 @@ EOF } base_onboard_usage_error() { - print_error "$*" + base_std_print_error "$*" printf "Run 'basectl onboard --help' for usage.\n" >&2 return 2 } diff --git a/cli/bash/commands/basectl/subcommands/project_command_helpers.sh b/cli/bash/commands/basectl/subcommands/project_command_helpers.sh index 04dd2a53..6575ed88 100644 --- a/cli/bash/commands/basectl/subcommands/project_command_helpers.sh +++ b/cli/bash/commands/basectl/subcommands/project_command_helpers.sh @@ -72,7 +72,7 @@ base_project_require_manifest_command_trust() { local wrapper="$BASE_HOME/bin/base-wrapper" [[ "$trust_required" == true ]] || return 0 - [[ -x "$wrapper" ]] || fatal_error "Base Python wrapper '$wrapper' is missing or is not executable." + [[ -x "$wrapper" ]] || base_std_fatal_error "Base Python wrapper '$wrapper' is missing or is not executable." "$wrapper" --project base base_trust require "$project" --manifest "$manifest_path" } @@ -100,7 +100,7 @@ base_project_activate_environment() { PATH="$venv_dir/bin:$PATH" export PATH elif [[ "$dry_run" != "1" ]]; then - log_warn "Project virtual environment was not found at '$venv_dir'. $venv_fix" + base_std_log_warn "Project virtual environment was not found at '$venv_dir'. $venv_fix" fi printf '%s\n' "$venv_dir" @@ -166,7 +166,7 @@ base_project_run_shell_command() { export BASE_CLI_PROJECT_MANIFEST="${BASE_PROJECT_MANIFEST:-}" # A project command gets its own owner-scoped bundle. Keep the parent # history ID, but do not let it write raw logs into Base's bundle. - unset BASE_CLI_RUN_ROOT BASE_CLI_RUN_ID BASE_CLI_PRIMARY_LOG + unset BASE_CLI_RUN_ROOT BASE_CLI_RUN_ID BASE_BASH_LIBS_PRIMARY_LOG # setup and diagnostics also recognize user-local tool installs. Keep # the project environment first, then make $HOME/.local/bin available # for runners such as uv and mise. @@ -189,10 +189,10 @@ base_validate_command_runner() { if command -v uv >/dev/null 2>&1 || [[ -n "${HOME:-}" && -x "$HOME/.local/bin/uv" ]]; then return 0 fi - fatal_error "Command runner 'uv' is not available. Install uv or remove runner: uv from the project manifest." + base_std_fatal_error "Command runner 'uv' is not available. Install uv or remove runner: uv from the project manifest." ;; *) - fatal_error "Unsupported command runner '$runner'." + base_std_fatal_error "Unsupported command runner '$runner'." ;; esac } diff --git a/cli/bash/commands/basectl/subcommands/projects.sh b/cli/bash/commands/basectl/subcommands/projects.sh index 0897b1f8..3a8f0374 100644 --- a/cli/bash/commands/basectl/subcommands/projects.sh +++ b/cli/bash/commands/basectl/subcommands/projects.sh @@ -22,7 +22,7 @@ EOF base_projects_usage_error() { base_projects_subcommand_usage >&2 - print_error "$*" + base_std_print_error "$*" return 2 } @@ -68,8 +68,8 @@ base_projects_source_python() { } base_projects_list_pre_setup_error() { - print_error "basectl projects list needs either the Base project virtualenv or a Python 3 with Click and PyYAML available." - print_error "Run 'basectl setup' to create the Base project virtualenv." + base_std_print_error "basectl projects list needs either the Base project virtualenv or a Python 3 with Click and PyYAML available." + base_std_print_error "Run 'basectl setup' to create the Base project virtualenv." return 1 } @@ -79,7 +79,7 @@ base_projects_run_list() { local python_bin local base_pythonpath - [[ -x "$wrapper" ]] || fatal_error "Base Python wrapper '$wrapper' is missing or is not executable." + [[ -x "$wrapper" ]] || base_std_fatal_error "Base Python wrapper '$wrapper' is missing or is not executable." venv_python="$(base_projects_base_venv_python)" if [[ -x "$venv_python" ]]; then diff --git a/cli/bash/commands/basectl/subcommands/prompt.sh b/cli/bash/commands/basectl/subcommands/prompt.sh index 63749bc3..146b255b 100644 --- a/cli/bash/commands/basectl/subcommands/prompt.sh +++ b/cli/bash/commands/basectl/subcommands/prompt.sh @@ -57,7 +57,7 @@ EOF base_prompt_usage_error() { base_prompt_subcommand_usage >&2 - print_error "$*" + base_std_print_error "$*" return 2 } @@ -115,7 +115,7 @@ base_prompt_subcommand_main() { ((debug)) && renderer_args+=(--debug) [[ -z "$output_path" ]] || output_args+=(--output "$output_path") - [[ -x "$wrapper" ]] || fatal_error "Base Python wrapper '$wrapper' is missing or is not executable." + [[ -x "$wrapper" ]] || base_std_fatal_error "Base Python wrapper '$wrapper' is missing or is not executable." BASE_CLI_DISPLAY_COMMAND="basectl prompt" \ "$wrapper" --project base base_prompt \ "${renderer_args[@]}" "${prompt_args[@]}" "${output_args[@]}" diff --git a/cli/bash/commands/basectl/subcommands/release.sh b/cli/bash/commands/basectl/subcommands/release.sh index 5c762d5c..584490a1 100644 --- a/cli/bash/commands/basectl/subcommands/release.sh +++ b/cli/bash/commands/basectl/subcommands/release.sh @@ -116,7 +116,7 @@ base_release_args_request_help() { base_release_usage_error() { base_release_subcommand_usage >&2 - print_error "$*" + base_std_print_error "$*" return 2 } @@ -142,6 +142,6 @@ base_release_subcommand_main() { return $? fi - [[ -x "$wrapper" ]] || fatal_error "Base Python wrapper '$wrapper' is missing or is not executable." + [[ -x "$wrapper" ]] || base_std_fatal_error "Base Python wrapper '$wrapper' is missing or is not executable." BASE_CLI_DISPLAY_COMMAND="basectl release" "$wrapper" --project base base_release "$@" } diff --git a/cli/bash/commands/basectl/subcommands/repo.sh b/cli/bash/commands/basectl/subcommands/repo.sh index 2be188d1..865ee74f 100644 --- a/cli/bash/commands/basectl/subcommands/repo.sh +++ b/cli/bash/commands/basectl/subcommands/repo.sh @@ -222,7 +222,7 @@ base_repo_print_usage_error() { local help_command="$1" shift - print_error "$*" + base_std_print_error "$*" printf "Run '%s --help' for usage.\n" "$help_command" >&2 return 2 } @@ -260,7 +260,7 @@ base_repo_load_installer_template() { module_path="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)/repo_installer_template.sh" || return 1 [[ -f "$module_path" ]] || { - log_error "repo installer-template helper was not found at '$module_path'." + base_std_log_error "repo installer-template helper was not found at '$module_path'." return 1 } # shellcheck source=cli/bash/commands/basectl/subcommands/repo_installer_template.sh @@ -276,7 +276,7 @@ base_repo_load_agent_guidance() { module_path="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)/repo_agent_guidance.sh" || return 1 [[ -f "$module_path" ]] || { - log_error "repo agent-guidance helper was not found at '$module_path'." + base_std_log_error "repo agent-guidance helper was not found at '$module_path'." return 1 } # shellcheck source=cli/bash/commands/basectl/subcommands/repo_agent_guidance.sh @@ -292,7 +292,7 @@ base_repo_load_github_settings() { module_path="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)/repo_github_settings.sh" || return 1 [[ -f "$module_path" ]] || { - log_error "repo GitHub settings helper was not found at '$module_path'." + base_std_log_error "repo GitHub settings helper was not found at '$module_path'." return 1 } # shellcheck source=cli/bash/commands/basectl/subcommands/repo_github_settings.sh @@ -367,7 +367,7 @@ base_repo_strip_config_value() { local value="$1" value="${value%%#*}" - str_trim value + base_str_trim value case "$value" in \"*\") @@ -420,12 +420,12 @@ base_repo_configured_workspace_root() { if ((in_workspace)) && [[ "$line" =~ ^[[:space:]]+root:[[:space:]]*(.*)$ ]]; then value="$(base_repo_strip_config_value "${BASH_REMATCH[1]}")" [[ -n "$value" ]] || { - log_error "$config_path: workspace.root must be a non-empty path." + base_std_log_error "$config_path: workspace.root must be a non-empty path." return 2 } value="$(base_repo_expand_path "$value")" [[ "$value" = /* ]] || { - log_error "$config_path: workspace.root must be an absolute path or start with '~'." + base_std_log_error "$config_path: workspace.root must be an absolute path or start with '~'." return 2 } printf '%s\n' "$value" @@ -459,7 +459,7 @@ base_repo_configured_github_value() { if ((in_github)) && [[ "$line" =~ ^[[:space:]]+${key}:[[:space:]]*(.*)$ ]]; then value="$(base_repo_strip_config_value "${BASH_REMATCH[1]}")" [[ -n "$value" ]] || { - log_error "$config_path: github.$key must be a non-empty value." + base_std_log_error "$config_path: github.$key must be a non-empty value." return 2 } printf '%s\n' "$value" @@ -488,7 +488,7 @@ base_repo_default_workspace_root() { esac [[ -n "${BASE_HOME:-}" ]] || { - log_error "BASE_HOME is required to resolve the default repository path." + base_std_log_error "BASE_HOME is required to resolve the default repository path." return 1 } cd -- "$BASE_HOME/.." && pwd -P @@ -542,7 +542,7 @@ base_repo_clone_protocol() { printf '%s\n' "$protocol" ;; *) - log_error "$HOME/.base.d/config.yaml: github.clone_protocol must be 'ssh' or 'https'." + base_std_log_error "$HOME/.base.d/config.yaml: github.clone_protocol must be 'ssh' or 'https'." return 2 ;; esac @@ -581,7 +581,7 @@ base_repo_create_directory() { return 0 fi - log_error "Failed to create parent directory '$target_dir'." + base_std_log_error "Failed to create parent directory '$target_dir'." return 1 } @@ -591,7 +591,7 @@ base_repo_write_stream() { local target_dir if [[ -e "$target" ]]; then - log_info "File already exists at '$target'; leaving it unchanged." + base_std_log_info "File already exists at '$target'; leaving it unchanged." return 0 fi @@ -603,7 +603,7 @@ base_repo_write_stream() { target_dir="$(dirname -- "$target")" base_repo_create_directory "$target_dir" || return 1 if ! cat 2>/dev/null > "$target"; then - log_error "Failed to write '$target'." + base_std_log_error "Failed to write '$target'." return 1 fi printf "Created '%s'.\n" "$target" @@ -615,7 +615,7 @@ base_repo_write_executable_stream() { local target_dir if [[ -e "$target" ]]; then - log_info "File already exists at '$target'; leaving it unchanged." + base_std_log_info "File already exists at '$target'; leaving it unchanged." return 0 fi @@ -627,11 +627,11 @@ base_repo_write_executable_stream() { target_dir="$(dirname -- "$target")" base_repo_create_directory "$target_dir" || return 1 if ! cat 2>/dev/null > "$target"; then - log_error "Failed to write '$target'." + base_std_log_error "Failed to write '$target'." return 1 fi if ! chmod +x "$target" 2>/dev/null; then - log_error "Failed to make '$target' executable." + base_std_log_error "Failed to make '$target' executable." return 1 fi printf "Created executable '%s'.\n" "$target" @@ -828,12 +828,12 @@ base_repo_write_license() { case "$license_id" in AGPL-3.0-or-later) [[ -f "$source_license" ]] || { - log_error "Base AGPL license text '$source_license' was not found." + base_std_log_error "Base AGPL license text '$source_license' was not found." return 1 } canonical_license="$(base_repo_agpl_license_text "$source_license")" || { - log_error "Base AGPL license text '$source_license' did not contain the canonical AGPL terms." + base_std_log_error "Base AGPL license text '$source_license' did not contain the canonical AGPL terms." return 1 } @@ -860,13 +860,13 @@ EOF ;; Apache-2.0) [[ -f "$license_template" ]] || { - log_error "Apache-2.0 license template '$license_template' was not found." + base_std_log_error "Apache-2.0 license template '$license_template' was not found." return 1 } base_repo_write_stream "$dry_run" "$root/LICENSE" < "$license_template" ;; *) - log_error "Unsupported repository license '$license_id'. Expected: $(base_repo_license_display)" + base_std_log_error "Unsupported repository license '$license_id'. Expected: $(base_repo_license_display)" return 1 ;; esac @@ -942,7 +942,7 @@ base_repo_write_release_manifest() { fi [[ -f "$manifest_path" ]] || { - log_error "Release standardization requires '$manifest_path'." + base_std_log_error "Release standardization requires '$manifest_path'." printf " Run 'basectl repo init' first to create the Base repository baseline.\n" >&2 return 1 } @@ -966,7 +966,7 @@ base_repo_write_release_manifest() { printf ' repository: %s\n' "$github_repo" printf ' release_title: "{repository} v{version}"\n' } >> "$manifest_path" || { - log_error "Unable to append release metadata to '$manifest_path'." + base_std_log_error "Unable to append release metadata to '$manifest_path'." return 1 } printf "Created release metadata in '%s'.\n" "$manifest_path" @@ -1042,7 +1042,7 @@ base_repo_configure_release() { local root="$3" [[ -n "$github_repo" ]] || { - log_error "Release standardization requires a GitHub repository." + base_std_log_error "Release standardization requires a GitHub repository." return 1 } base_repo_write_release_manifest "$dry_run" "$github_repo" "$root" || return 1 @@ -1131,7 +1131,7 @@ EOF base_repo_project_intake_workflow_template_path() { [[ -n "${BASE_HOME:-}" ]] || { - log_error "BASE_HOME is required to locate the Project Intake workflow template." + base_std_log_error "BASE_HOME is required to locate the Project Intake workflow template." return 1 } @@ -1140,7 +1140,7 @@ base_repo_project_intake_workflow_template_path() { base_repo_issue_branch_policy_workflow_template_path() { [[ -n "${BASE_HOME:-}" ]] || { - log_error "BASE_HOME is required to locate the Issue Branch Policy workflow template." + base_std_log_error "BASE_HOME is required to locate the Issue Branch Policy workflow template." return 1 } @@ -1154,7 +1154,7 @@ base_repo_write_issue_branch_policy_workflow() { template="$(base_repo_issue_branch_policy_workflow_template_path)" || return 1 [[ -f "$template" ]] || { - log_error "Issue Branch Policy workflow template was not found at '$template'." + base_std_log_error "Issue Branch Policy workflow template was not found at '$template'." return 1 } @@ -1168,7 +1168,7 @@ base_repo_write_project_intake_workflow() { template="$(base_repo_project_intake_workflow_template_path)" || return 1 [[ -f "$template" ]] || { - log_error "Project Intake workflow template was not found at '$template'." + base_std_log_error "Project Intake workflow template was not found at '$template'." return 1 } @@ -1238,7 +1238,7 @@ base_repo_infer_github_repo() { local path="$1" local github_repo - gh_infer_repo_from_origin "$path" github_repo || return 1 + base_gh_infer_repo_from_origin "$path" github_repo || return 1 printf '%s\n' "$github_repo" } @@ -1268,7 +1268,7 @@ base_repo_bootstrap_github_checkout() { if [[ ! -d "$root/.git" ]]; then git init -b main "$root" >/dev/null 2>&1 || { - log_error "Failed to initialize Git repository at '$root'." + base_std_log_error "Failed to initialize Git repository at '$root'." return 1 } fi @@ -1276,12 +1276,12 @@ base_repo_bootstrap_github_checkout() { if origin_url="$(git -C "$root" remote get-url origin 2>/dev/null)"; then origin_repo="$(base_repo_infer_github_repo "$root" 2>/dev/null || true)" if [[ "$origin_repo" != "$repo" ]]; then - log_error "New GitHub repository '$repo' cannot be bootstrapped because '$root' already has origin '$origin_url'. Remove or correct that origin, then retry." + base_std_log_error "New GitHub repository '$repo' cannot be bootstrapped because '$root' already has origin '$origin_url'. Remove or correct that origin, then retry." return 1 fi else git -C "$root" remote add origin "$remote_url" || { - log_error "Failed to attach GitHub origin '$remote_url' to '$root'." + base_std_log_error "Failed to attach GitHub origin '$remote_url' to '$root'." return 1 } fi @@ -1290,7 +1290,7 @@ base_repo_bootstrap_github_checkout() { # intent-driven path can publish an extracted project as one coherent # initial commit. Existing remotes never reach this function. git -C "$root" add -A || { - log_error "Failed to stage the initial repository contents in '$root'." + base_std_log_error "Failed to stage the initial repository contents in '$root'." return 1 } @@ -1299,7 +1299,7 @@ base_repo_bootstrap_github_checkout() { branch="$(git -C "$root" branch --show-current)" else git -C "$root" checkout -b main >/dev/null 2>&1 || { - log_error "Failed to select the initial 'main' branch in '$root'." + base_std_log_error "Failed to select the initial 'main' branch in '$root'." return 1 } branch="main" @@ -1307,16 +1307,16 @@ base_repo_bootstrap_github_checkout() { else if ! git -C "$root" rev-parse --verify HEAD >/dev/null 2>&1; then git -C "$root" checkout -b main >/dev/null 2>&1 || { - log_error "Failed to select the initial 'main' branch in '$root'." + base_std_log_error "Failed to select the initial 'main' branch in '$root'." return 1 } git -C "$root" commit -m "Initial repository commit" || { - log_error "Failed to create the initial repository commit." + base_std_log_error "Failed to create the initial repository commit." return 1 } else git -C "$root" commit -m "Add Base repository baseline" || { - log_error "Failed to commit the Base repository baseline." + base_std_log_error "Failed to commit the Base repository baseline." return 1 } fi @@ -1324,19 +1324,19 @@ base_repo_bootstrap_github_checkout() { fi [[ -n "$branch" ]] || { - log_error "Unable to determine the branch to publish from '$root'." + base_std_log_error "Unable to determine the branch to publish from '$root'." return 1 } git -C "$root" push -u origin "$branch" || { - log_error "Failed to push the initial repository branch '$branch' to origin." + base_std_log_error "Failed to push the initial repository branch '$branch' to origin." return 1 } - log_info "Bootstrapped '$repo' from '$root' on branch '$branch'." + base_std_log_info "Bootstrapped '$repo' from '$root' on branch '$branch'." } base_repo_require_gh() { - gh_require_cli "GitHub CLI 'gh' is required for repository configuration." || return 1 - gh_auth_status_diagnostics "Run 'gh auth login -h github.com' and retry." + base_gh_require_cli "GitHub CLI 'gh' is required for repository configuration." || return 1 + base_gh_auth_status_diagnostics "Run 'gh auth login -h github.com' and retry." } base_repo_pretty_quote() { @@ -1426,10 +1426,10 @@ base_repo_languages_csv() { base_repo_join_csv() { local joined="" - # shellcheck disable=SC2034 # Passed by name to str_join. + # shellcheck disable=SC2034 # Passed by name to base_str_join. local values=("$@") - str_join joined ", " values + base_str_join joined ", " values printf '%s' "$joined" } @@ -1474,11 +1474,11 @@ base_repo_pr_issue_category() { printf '%s\n' "$category" ;; 2) - log_error "GitHub issue #$issue in '$repo' must have exactly one category label: bug, enhancement, documentation, ci, or security." + base_std_log_error "GitHub issue #$issue in '$repo' must have exactly one category label: bug, enhancement, documentation, ci, or security." return 1 ;; *) - log_error "Unable to determine the category label for GitHub issue #$issue in '$repo'." + base_std_log_error "Unable to determine the category label for GitHub issue #$issue in '$repo'." return 1 ;; esac @@ -1490,9 +1490,9 @@ base_repo_print_pr_worktree_root_hint() { local repository_root="$3" if [[ "$command_label" == "repo init --pr" ]]; then - log_error "repo init --pr expects --path to point at the repository root." + base_std_log_error "repo init --pr expects --path to point at the repository root." else - log_error "$command_label expects the target path to point at the repository root." + base_std_log_error "$command_label expects the target path to point at the repository root." fi printf " Provided path: %s\n" "$provided_path" >&2 printf " Repository root: %s\n" "$repository_root" >&2 @@ -1545,12 +1545,12 @@ base_repo_require_pr_worktree() { local root="$1" [[ -d "$root" ]] || { - log_error "$command_label requires '$root' to be an existing Git worktree." + base_std_log_error "$command_label requires '$root' to be an existing Git worktree." return 1 } git_root="$(git -C "$root" rev-parse --show-toplevel 2>/dev/null)" || { - log_error "$command_label requires '$root' to be an existing Git worktree." + base_std_log_error "$command_label requires '$root' to be an existing Git worktree." return 1 } git_root="$(cd -- "$git_root" && pwd -P)" || return 1 @@ -1563,7 +1563,7 @@ base_repo_require_pr_worktree() { dirty_status="$(git -C "$root" status --porcelain)" [[ -z "$dirty_status" ]] || { - log_error "$command_label requires a clean Git worktree at '$root'." + base_std_log_error "$command_label requires a clean Git worktree at '$root'." base_repo_print_pr_worktree_dirty_hint "$root" "$dirty_status" return 1 } @@ -1574,8 +1574,8 @@ base_repo_default_branch_for_pr() { local repo="$1" base_repo_require_gh || return 1 - if ! gh_repo_default_branch "$repo" base_remote_default_branch; then - log_error "Unable to determine the default branch for GitHub repository '$repo'." + if ! base_gh_repo_default_branch "$repo" base_remote_default_branch; then + base_std_log_error "Unable to determine the default branch for GitHub repository '$repo'." return 1 fi @@ -1586,7 +1586,7 @@ base_repo_detect_default_branch() { local base_default_branch local root="$1" - if git_detect_default_branch "$root" base_default_branch; then + if base_git_detect_default_branch "$root" base_default_branch; then printf '%s\n' "$base_default_branch" return 0 fi @@ -1609,7 +1609,7 @@ base_repo_prepare_pr_branch() { if git -C "$root" show-ref --verify --quiet "refs/heads/$branch"; then git -C "$root" switch "$branch" || { - log_error "Failed to switch to branch '$branch'." + base_std_log_error "Failed to switch to branch '$branch'." return 1 } else @@ -1618,18 +1618,18 @@ base_repo_prepare_pr_branch() { elif git -C "$root" show-ref --verify --quiet "refs/remotes/origin/$default_branch"; then start_point="origin/$default_branch" else - log_error "Unable to find default branch '$default_branch' in '$root'." + base_std_log_error "Unable to find default branch '$default_branch' in '$root'." return 1 fi git -C "$root" switch -c "$branch" "$start_point" || { - log_error "Failed to create branch '$branch'." + base_std_log_error "Failed to create branch '$branch'." return 1 } fi [[ -z "$(git -C "$root" status --porcelain)" ]] || { - log_error "$command_label requires branch '$branch' to have a clean Git worktree." + base_std_log_error "$command_label requires branch '$branch' to have a clean Git worktree." return 1 } } @@ -1646,12 +1646,12 @@ base_repo_stage_pr_files() { done ((${#files[@]})) || { - log_error "No $description exist to stage." + base_std_log_error "No $description exist to stage." return 1 } git -C "$root" add -- "${files[@]}" || { - log_error "Failed to stage $description." + base_std_log_error "Failed to stage $description." return 1 } } @@ -1716,16 +1716,16 @@ base_repo_finish_generated_pr() { base_repo_stage_pr_files "$root" "$file_description" "$@" || return 1 if git -C "$root" diff --cached --quiet --; then - log_info "No $file_description changes to commit; skipping pull request creation." + base_std_log_info "No $file_description changes to commit; skipping pull request creation." return 0 fi git -C "$root" commit -m "$commit_message" || { - log_error "Failed to commit $file_description." + base_std_log_error "Failed to commit $file_description." return 1 } git -C "$root" push -u origin "$branch" || { - log_error "Failed to push branch '$branch' to origin." + base_std_log_error "Failed to push branch '$branch' to origin." return 1 } @@ -1878,25 +1878,25 @@ base_repo_finish_pr_baseline() { base_repo_stage_pr_baseline_files "$root" "$agent_ready" "$release_contract" || return 1 if git -C "$root" diff --cached --quiet --; then - log_info "No repository baseline changes to commit; skipping pull request creation." + base_std_log_info "No repository baseline changes to commit; skipping pull request creation." return 0 fi git -C "$root" commit -m "Add Base repository baseline" || { - log_error "Failed to commit repository baseline files." + base_std_log_error "Failed to commit repository baseline files." return 1 } git -C "$root" push -u origin "$branch" || { - log_error "Failed to push branch '$branch' to origin." + base_std_log_error "Failed to push branch '$branch' to origin." return 1 } - std_make_temp_file body_file base-repo-init-pr || { - log_error "Failed to create a temporary pull request body file." + base_std_make_temp_file body_file base-repo-init-pr || { + base_std_log_error "Failed to create a temporary pull request body file." return 1 } - std_make_temp_file output_file base-repo-init-pr-output || { - log_error "Failed to create a temporary pull request output file." + base_std_make_temp_file output_file base-repo-init-pr-output || { + base_std_log_error "Failed to create a temporary pull request output file." return 1 } base_repo_create_baseline_pr_body "$name" "$root" "$repo" "$issue" "$command_hint" > "$body_file" @@ -2223,7 +2223,7 @@ base_repo_init() { base_repo_init_usage_error "Option '--language' must not contain empty entries." return $? fi - str_split language_fields "$language_option" "," + base_str_split language_fields "$language_option" "," for language_field in "${language_fields[@]}"; do normalized_language="$(base_repo_normalize_language "$language_field" || true)" if [[ -z "$normalized_language" ]]; then @@ -2252,7 +2252,7 @@ base_repo_init() { base_repo_init_usage_error "Option '--language' must not contain empty entries." return $? fi - str_split language_fields "$language_option" "," + base_str_split language_fields "$language_option" "," for language_field in "${language_fields[@]}"; do normalized_language="$(base_repo_normalize_language "$language_field" || true)" if [[ -z "$normalized_language" ]]; then @@ -2389,8 +2389,8 @@ base_repo_init() { shift ;; -v) - set_log_level DEBUG - export LOG_DEBUG=1 + base_std_set_log_level DEBUG + export BASE_BASH_LIBS_LOG_DEBUG=1 shift ;; -*) @@ -2463,7 +2463,7 @@ base_repo_init() { pr_category="$issue_category" fi pr_branch="$(base_repo_pr_branch_name "$pr_category" "$issue" "repo-baseline" "$name")" || { - log_error "Unable to generate the canonical issue branch for repo init --pr." + base_std_log_error "Unable to generate the canonical issue branch for repo init --pr." return 1 } if [[ "$dry_run" == "1" ]]; then @@ -2528,9 +2528,9 @@ base_repo_init() { case "$baseline_change_status" in 1) if ((configure)); then - log_info "No repository baseline changes to commit; continuing with GitHub repository configuration." + base_std_log_info "No repository baseline changes to commit; continuing with GitHub repository configuration." else - log_info "No repository baseline changes to commit; GitHub repository configuration skipped by --no-configure." + base_std_log_info "No repository baseline changes to commit; GitHub repository configuration skipped by --no-configure." fi ;; *) @@ -2579,7 +2579,7 @@ base_repo_clone_check_destination() { [[ -e "$target" ]] || return 0 if [[ ! -d "$target" ]]; then - log_error "Destination '$target' already exists but is not a matching Git checkout." + base_std_log_error "Destination '$target' already exists but is not a matching Git checkout." return 1 fi @@ -2591,12 +2591,12 @@ base_repo_clone_check_destination() { fi if [[ -n "$actual_repo" ]]; then - log_error "Destination '$target' already points at GitHub repository '$actual_repo'." - log_error "Expected '$expected_repo'." + base_std_log_error "Destination '$target' already points at GitHub repository '$actual_repo'." + base_std_log_error "Expected '$expected_repo'." return 1 fi - log_error "Destination '$target' already exists but is not a matching Git checkout." + base_std_log_error "Destination '$target' already exists but is not a matching Git checkout." return 1 } @@ -2633,7 +2633,7 @@ base_repo_clone_with_gh() { fi command -v gh >/dev/null 2>&1 || { - log_error "GitHub CLI 'gh' is required for repository clone." + base_std_log_error "GitHub CLI 'gh' is required for repository clone." return 1 } @@ -2641,7 +2641,7 @@ base_repo_clone_with_gh() { base_repo_create_directory "$parent" || return 1 printf "Cloning GitHub repository '%s' into '%s'.\n" "$repo" "$target" gh repo clone "$repo" "$target" || { - log_error "Failed to clone GitHub repository '$repo' into '$target'." + base_std_log_error "Failed to clone GitHub repository '$repo' into '$target'." return 1 } printf "Cloned '%s' to '%s'.\n" "$repo" "$target" @@ -2698,8 +2698,8 @@ base_repo_clone() { shift ;; -v) - set_log_level DEBUG - export LOG_DEBUG=1 + base_std_set_log_level DEBUG + export BASE_BASH_LIBS_LOG_DEBUG=1 shift ;; -*) @@ -2923,8 +2923,8 @@ base_repo_check() { shift 2 ;; -v) - set_log_level DEBUG - export LOG_DEBUG=1 + base_std_set_log_level DEBUG + export BASE_BASH_LIBS_LOG_DEBUG=1 shift ;; -*) @@ -3073,8 +3073,8 @@ base_repo_configure() { shift ;; -v) - set_log_level DEBUG - export LOG_DEBUG=1 + base_std_set_log_level DEBUG + export BASE_BASH_LIBS_LOG_DEBUG=1 shift ;; -*) @@ -3098,7 +3098,7 @@ base_repo_configure() { github_repo="$(base_repo_infer_github_repo "$path" || true)" fi [[ -n "$github_repo" ]] || { - log_error "Unable to infer GitHub repository from '$path'." + base_std_log_error "Unable to infer GitHub repository from '$path'." printf " Inference requires a git remote named 'origin' that points to github.com.\n" >&2 printf " Pass --repo to configure explicitly, or run:\n" >&2 printf " git -C %s remote -v\n" "$(base_repo_pretty_arg "$path")" >&2 diff --git a/cli/bash/commands/basectl/subcommands/repo_agent_guidance.sh b/cli/bash/commands/basectl/subcommands/repo_agent_guidance.sh index 5d6054fb..dbc52a14 100644 --- a/cli/bash/commands/basectl/subcommands/repo_agent_guidance.sh +++ b/cli/bash/commands/basectl/subcommands/repo_agent_guidance.sh @@ -325,8 +325,8 @@ base_repo_finish_agent_guidance_pr() { return $? fi - std_make_temp_file body_file base-repo-agent-guidance-pr || { - log_error "Failed to create a temporary pull request body file." + base_std_make_temp_file body_file base-repo-agent-guidance-pr || { + base_std_log_error "Failed to create a temporary pull request body file." return 1 } base_repo_create_agent_guidance_pr_body "$repo_name" "$root" "$default_branch" "$validation_command" "$repo" "$issue" "$category" > "$body_file" @@ -460,8 +460,8 @@ base_repo_agent_guidance() { shift ;; -v) - set_log_level DEBUG - export LOG_DEBUG=1 + base_std_set_log_level DEBUG + export BASE_BASH_LIBS_LOG_DEBUG=1 shift ;; -*) @@ -536,7 +536,7 @@ base_repo_agent_guidance() { pr_category="$issue_category" fi pr_branch="$(base_repo_pr_branch_name "$pr_category" "$issue" "agent-guidance" "$repo_name")" || { - log_error "Unable to generate the canonical issue branch for repo agent-guidance --pr." + base_std_log_error "Unable to generate the canonical issue branch for repo agent-guidance --pr." return 1 } if [[ "$dry_run" == "1" ]]; then diff --git a/cli/bash/commands/basectl/subcommands/repo_github_settings.sh b/cli/bash/commands/basectl/subcommands/repo_github_settings.sh index ea0f0af9..abd1d12d 100644 --- a/cli/bash/commands/basectl/subcommands/repo_github_settings.sh +++ b/cli/bash/commands/basectl/subcommands/repo_github_settings.sh @@ -25,7 +25,7 @@ base_repo_homebrew_gh_outdated() { base_repo_warn_if_gh_outdated() { if base_repo_homebrew_gh_outdated; then - log_warn "GitHub CLI 'gh' is outdated; run 'basectl setup --profile dev' to upgrade Base-managed developer prerequisites." + base_std_log_warn "GitHub CLI 'gh' is outdated; run 'basectl setup --profile dev' to upgrade Base-managed developer prerequisites." fi } @@ -63,11 +63,11 @@ base_repo_ensure_github_repo() { base_repo_require_gh || return 1 if gh repo view "$repo" >/dev/null 2>&1; then - log_info "GitHub repository '$repo' already exists." + base_std_log_info "GitHub repository '$repo' already exists." return 0 fi - log_info "Creating $visibility GitHub repository '$repo'." + base_std_log_info "Creating $visibility GitHub repository '$repo'." gh repo create "$repo" "--$visibility" --description "$description" || return 1 BASE_REPO_GITHUB_REPO_CREATED=1 } @@ -132,12 +132,12 @@ base_repo_configure_default_branch_protection() { ruleset_lookup_output="$(gh api "repos/$repo/rulesets" \ --jq 'map(select(.name == "Base default branch protection" and .source_type == "Repository")) | .[0].id // ""' 2>&1)" || { if base_repo_rulesets_plan_gated_error "$ruleset_lookup_output"; then - log_warn "Default branch protection skipped for '$repo'." - log_warn "$ruleset_lookup_output" + base_std_log_warn "Default branch protection skipped for '$repo'." + base_std_log_warn "$ruleset_lookup_output" return 0 fi - [[ -z "$ruleset_lookup_output" ]] || log_error "$ruleset_lookup_output" - log_error "Unable to inspect GitHub rulesets for '$repo'." + [[ -z "$ruleset_lookup_output" ]] || base_std_log_error "$ruleset_lookup_output" + base_std_log_error "Unable to inspect GitHub rulesets for '$repo'." return 1 } ruleset_id="$ruleset_lookup_output" @@ -145,24 +145,24 @@ base_repo_configure_default_branch_protection() { if [[ -n "$ruleset_id" ]]; then ruleset_write_output="$(printf '%s\n' "$payload" | gh api "repos/$repo/rulesets/$ruleset_id" --method PUT --input - 2>&1)" || { if base_repo_rulesets_plan_gated_error "$ruleset_write_output"; then - log_warn "Default branch protection skipped for '$repo'." - log_warn "$ruleset_write_output" + base_std_log_warn "Default branch protection skipped for '$repo'." + base_std_log_warn "$ruleset_write_output" return 0 fi - [[ -z "$ruleset_write_output" ]] || log_error "$ruleset_write_output" - log_error "Unable to update Base default branch protection ruleset for '$repo'." + [[ -z "$ruleset_write_output" ]] || base_std_log_error "$ruleset_write_output" + base_std_log_error "Unable to update Base default branch protection ruleset for '$repo'." return 1 } printf " Branch protection: updated 'Base default branch protection'.\n" else ruleset_write_output="$(printf '%s\n' "$payload" | gh api "repos/$repo/rulesets" --method POST --input - 2>&1)" || { if base_repo_rulesets_plan_gated_error "$ruleset_write_output"; then - log_warn "Default branch protection skipped for '$repo'." - log_warn "$ruleset_write_output" + base_std_log_warn "Default branch protection skipped for '$repo'." + base_std_log_warn "$ruleset_write_output" return 0 fi - [[ -z "$ruleset_write_output" ]] || log_error "$ruleset_write_output" - log_error "Unable to create Base default branch protection ruleset for '$repo'." + [[ -z "$ruleset_write_output" ]] || base_std_log_error "$ruleset_write_output" + base_std_log_error "Unable to create Base default branch protection ruleset for '$repo'." return 1 } printf " Branch protection: created 'Base default branch protection'.\n" @@ -192,8 +192,8 @@ base_repo_remote_issue_branch_policy_ready() { if [[ "$output" == *"(HTTP 404)"* ]]; then return 1 fi - [[ -z "$output" ]] || log_error "$output" - log_error "Unable to verify the Issue Branch Policy workflow on '$repo'." + [[ -z "$output" ]] || base_std_log_error "$output" + base_std_log_error "Unable to verify the Issue Branch Policy workflow on '$repo'." return 2 } workflow_state="$output" @@ -202,16 +202,16 @@ base_repo_remote_issue_branch_policy_ready() { fi output="$(gh api "repos/$repo" --jq '.default_branch' 2>&1)" || { - [[ -z "$output" ]] || log_error "$output" - log_error "Unable to determine the default branch for '$repo'." + [[ -z "$output" ]] || base_std_log_error "$output" + base_std_log_error "Unable to determine the default branch for '$repo'." return 2 } default_branch="$output" [[ -n "$default_branch" ]] || return 1 run_json="$(gh api "repos/$repo/actions/workflows/issue-branch-policy.yml/runs?status=success&per_page=100" 2>&1)" || { - [[ -z "$run_json" ]] || log_error "$run_json" - log_error "Unable to inspect successful Issue Branch Policy runs on '$repo'." + [[ -z "$run_json" ]] || base_std_log_error "$run_json" + base_std_log_error "Unable to inspect successful Issue Branch Policy runs on '$repo'." return 2 } output="$(jq -r \ @@ -224,8 +224,8 @@ base_repo_remote_issue_branch_policy_ready() { .path == ".github/workflows/issue-branch-policy.yml" ) | [.id, .head_sha, .updated_at, .html_url] | @tsv' \ <<< "$run_json" 2>&1)" || { - [[ -z "$output" ]] || log_error "$output" - log_error "Unable to parse successful Issue Branch Policy runs on '$repo'." + [[ -z "$output" ]] || base_std_log_error "$output" + base_std_log_error "Unable to parse successful Issue Branch Policy runs on '$repo'." return 2 } eligible_runs="$output" @@ -241,15 +241,15 @@ base_repo_remote_issue_branch_policy_ready() { ! "$run_sha" =~ ^[0-9a-f]{40}$ || ! "$run_timestamp" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$ || "$run_target_url" != "https://github.com/$repo/actions/runs/$run_id" ]]; then - log_error "GitHub returned malformed Issue Branch Policy run metadata for '$repo'." + base_std_log_error "GitHub returned malformed Issue Branch Policy run metadata for '$repo'." return 2 fi [[ "$run_timestamp" > "$cutoff_timestamp" ]] || continue output="$(gh api --paginate --slurp \ "repos/$repo/commits/$run_sha/statuses?per_page=100" 2>&1)" || { - [[ -z "$output" ]] || log_error "$output" - log_error "Unable to verify the Issue Branch Policy status source on '$repo'." + [[ -z "$output" ]] || base_std_log_error "$output" + base_std_log_error "Unable to verify the Issue Branch Policy status source on '$repo'." return 2 } status_creator="$(jq -r \ @@ -269,8 +269,8 @@ base_repo_remote_issue_branch_policy_ready() { ((ready_run_found == 1)) || return 1 output="$(gh api /apps/github-actions --jq '.id' 2>&1)" || { - [[ -z "$output" ]] || log_error "$output" - log_error "Unable to verify the GitHub Actions integration id." + [[ -z "$output" ]] || base_std_log_error "$output" + base_std_log_error "Unable to verify the GitHub Actions integration id." return 2 } actions_app_id="$output" @@ -287,8 +287,8 @@ base_repo_current_issue_branch_policy_integration_id() { if base_repo_rulesets_plan_gated_error "$output"; then return 1 fi - [[ -z "$output" ]] || log_error "$output" - log_error "Unable to inspect current default branch protection for '$repo'." + [[ -z "$output" ]] || base_std_log_error "$output" + base_std_log_error "Unable to inspect current default branch protection for '$repo'." return 2 } ruleset_id="$output" @@ -296,8 +296,8 @@ base_repo_current_issue_branch_policy_integration_id() { output="$(gh api "repos/$repo/rulesets/$ruleset_id" \ --jq '[.rules[]? | select(.type == "required_status_checks") | .parameters.required_status_checks[]? | select(.context == "base/issue-branch-policy") | (.integration_id // 0)] | first // ""' 2>&1)" || { - [[ -z "$output" ]] || log_error "$output" - log_error "Unable to inspect the current Issue Branch Policy requirement on '$repo'." + [[ -z "$output" ]] || base_std_log_error "$output" + base_std_log_error "Unable to inspect the current Issue Branch Policy requirement on '$repo'." return 2 } [[ -n "$output" ]] || return 1 @@ -328,12 +328,12 @@ base_repo_configure_branch_naming() { ruleset_lookup_output="$(gh api "repos/$repo/rulesets" \ --jq 'map(select(.name == "Base branch naming" and .source_type == "Repository")) | .[0].id // ""' 2>&1)" || { if base_repo_rulesets_plan_gated_error "$ruleset_lookup_output"; then - log_warn "Branch naming enforcement skipped for '$repo'." - log_warn "$ruleset_lookup_output" + base_std_log_warn "Branch naming enforcement skipped for '$repo'." + base_std_log_warn "$ruleset_lookup_output" return 0 fi - [[ -z "$ruleset_lookup_output" ]] || log_error "$ruleset_lookup_output" - log_error "Unable to inspect GitHub rulesets for '$repo'." + [[ -z "$ruleset_lookup_output" ]] || base_std_log_error "$ruleset_lookup_output" + base_std_log_error "Unable to inspect GitHub rulesets for '$repo'." return 1 } ruleset_id="$ruleset_lookup_output" @@ -341,34 +341,34 @@ base_repo_configure_branch_naming() { if [[ -n "$ruleset_id" ]]; then ruleset_write_output="$(printf '%s\n' "$payload" | gh api "repos/$repo/rulesets/$ruleset_id" --method PUT --input - 2>&1)" || { if base_repo_rulesets_plan_gated_error "$ruleset_write_output"; then - log_warn "Branch naming enforcement skipped for '$repo'." - log_warn "$ruleset_write_output" + base_std_log_warn "Branch naming enforcement skipped for '$repo'." + base_std_log_warn "$ruleset_write_output" return 0 fi if base_repo_branch_name_rule_unavailable_error "$ruleset_write_output"; then - log_warn "Branch naming ruleset unavailable for '$repo'; issue branch policy workflow remains the fallback." - log_warn "$ruleset_write_output" + base_std_log_warn "Branch naming ruleset unavailable for '$repo'; issue branch policy workflow remains the fallback." + base_std_log_warn "$ruleset_write_output" return 0 fi - [[ -z "$ruleset_write_output" ]] || log_error "$ruleset_write_output" - log_error "Unable to update Base branch naming ruleset for '$repo'." + [[ -z "$ruleset_write_output" ]] || base_std_log_error "$ruleset_write_output" + base_std_log_error "Unable to update Base branch naming ruleset for '$repo'." return 1 } printf " Branch naming: updated 'Base branch naming'.\n" else ruleset_write_output="$(printf '%s\n' "$payload" | gh api "repos/$repo/rulesets" --method POST --input - 2>&1)" || { if base_repo_rulesets_plan_gated_error "$ruleset_write_output"; then - log_warn "Branch naming enforcement skipped for '$repo'." - log_warn "$ruleset_write_output" + base_std_log_warn "Branch naming enforcement skipped for '$repo'." + base_std_log_warn "$ruleset_write_output" return 0 fi if base_repo_branch_name_rule_unavailable_error "$ruleset_write_output"; then - log_warn "Branch naming ruleset unavailable for '$repo'; issue branch policy workflow remains the fallback." - log_warn "$ruleset_write_output" + base_std_log_warn "Branch naming ruleset unavailable for '$repo'; issue branch policy workflow remains the fallback." + base_std_log_warn "$ruleset_write_output" return 0 fi - [[ -z "$ruleset_write_output" ]] || log_error "$ruleset_write_output" - log_error "Unable to create Base branch naming ruleset for '$repo'." + [[ -z "$ruleset_write_output" ]] || base_std_log_error "$ruleset_write_output" + base_std_log_error "Unable to create Base branch naming ruleset for '$repo'." return 1 } printf " Branch naming: created 'Base branch naming'.\n" @@ -421,10 +421,10 @@ base_repo_check_project_intake_secret() { base_repo_require_gh || return 1 output="$(gh secret list --repo "$repo" 2>&1)" || { - log_warn "Unable to inspect GitHub Actions secrets for '$repo'." - [[ -z "$output" ]] || log_warn "$output" - log_warn "Project Intake may fail unless BASE_PROJECT_TOKEN is configured with user Project access." - log_warn "Fix: $(base_repo_project_intake_secret_fix_command "$repo")" + base_std_log_warn "Unable to inspect GitHub Actions secrets for '$repo'." + [[ -z "$output" ]] || base_std_log_warn "$output" + base_std_log_warn "Project Intake may fail unless BASE_PROJECT_TOKEN is configured with user Project access." + base_std_log_warn "Fix: $(base_repo_project_intake_secret_fix_command "$repo")" return 0 } @@ -432,9 +432,9 @@ base_repo_check_project_intake_secret() { return 0 fi - log_warn "Project Intake secret 'BASE_PROJECT_TOKEN' is not configured for '$repo'." - log_warn "GitHub Actions default token cannot access user-level Projects." - log_warn "Fix: $(base_repo_project_intake_secret_fix_command "$repo")" + base_std_log_warn "Project Intake secret 'BASE_PROJECT_TOKEN' is not configured for '$repo'." + base_std_log_warn "GitHub Actions default token cannot access user-level Projects." + base_std_log_warn "Fix: $(base_repo_project_intake_secret_fix_command "$repo")" } base_repo_configure_project_metadata() { @@ -495,7 +495,7 @@ base_repo_configure_project_metadata() { fi [[ -x "$wrapper" ]] || { - log_error "Base Python wrapper '$wrapper' is missing or is not executable." + base_std_log_error "Base Python wrapper '$wrapper' is missing or is not executable." return 1 } base_repo_check_project_intake_secret "$dry_run" "$repo" || return 1 @@ -524,8 +524,8 @@ base_repo_configure_project_metadata() { command+=(--initiative-option "$option") done - log_info "Configuring GitHub Project '$project_title' for '$repo'." - log_info "Running: $(base_repo_pretty_command "${command[@]}")" + base_std_log_info "Configuring GitHub Project '$project_title' for '$repo'." + base_std_log_info "Running: $(base_repo_pretty_command "${command[@]}")" output="$(BASE_CLI_DISPLAY_COMMAND="basectl gh" "${command[@]}" 2>&1)" || status=$? if [[ "$status" -eq 0 ]]; then [[ -z "$output" ]] || printf '%s\n' "$output" @@ -533,13 +533,13 @@ base_repo_configure_project_metadata() { return 0 fi if [[ "$status" -eq 3 ]]; then - log_warn "GitHub Project metadata skipped for '$repo'." - [[ -z "$output" ]] || log_warn "$output" + base_std_log_warn "GitHub Project metadata skipped for '$repo'." + [[ -z "$output" ]] || base_std_log_warn "$output" return 0 fi - [[ -z "$output" ]] || log_error "$output" - log_error "Unable to configure GitHub Project metadata for '$repo'." + [[ -z "$output" ]] || base_std_log_error "$output" + base_std_log_error "Unable to configure GitHub Project metadata for '$repo'." return 1 } @@ -602,13 +602,13 @@ base_repo_configure_github() { 1) if [[ "$current_issue_branch_policy_required" == "1" && "$current_issue_branch_policy_integration_id" == "$BASE_GITHUB_ACTIONS_INTEGRATION_ID" ]]; then issue_branch_policy_available=1 - log_warn "Preserving the existing Issue Branch Policy requirement on '$repo' without recent bootstrap evidence." + base_std_log_warn "Preserving the existing Issue Branch Policy requirement on '$repo' without recent bootstrap evidence." elif [[ "$current_issue_branch_policy_required" == "1" ]]; then - log_error "Refusing to replace the existing unbound Issue Branch Policy requirement on '$repo' without a recent trusted success." + base_std_log_error "Refusing to replace the existing unbound Issue Branch Policy requirement on '$repo' without a recent trusted success." return 1 else - log_warn "Issue branch policy is not required for '$repo' yet." - log_warn "Enable '.github/workflows/issue-branch-policy.yml', complete one recent successful run, and rerun 'basectl repo configure'." + base_std_log_warn "Issue branch policy is not required for '$repo' yet." + base_std_log_warn "Enable '.github/workflows/issue-branch-policy.yml', complete one recent successful run, and rerun 'basectl repo configure'." fi ;; *) return 1 ;; diff --git a/cli/bash/commands/basectl/subcommands/repo_installer_template.sh b/cli/bash/commands/basectl/subcommands/repo_installer_template.sh index 25e490a4..b77cbc5e 100644 --- a/cli/bash/commands/basectl/subcommands/repo_installer_template.sh +++ b/cli/bash/commands/basectl/subcommands/repo_installer_template.sh @@ -29,7 +29,7 @@ EOF base_repo_installer_template_path() { [[ -n "${BASE_HOME:-}" ]] || { - log_error "BASE_HOME is required to locate the project installer template." + base_std_log_error "BASE_HOME is required to locate the project installer template." return 1 } @@ -41,7 +41,7 @@ base_repo_print_installer_template() { template="$(base_repo_installer_template_path)" || return 1 [[ -f "$template" ]] || { - log_error "Project installer template was not found at '$template'." + base_std_log_error "Project installer template was not found at '$template'." return 1 } @@ -55,7 +55,7 @@ base_repo_write_installer_template() { template="$(base_repo_installer_template_path)" || return 1 [[ -f "$template" ]] || { - log_error "Project installer template was not found at '$template'." + base_std_log_error "Project installer template was not found at '$template'." return 1 } @@ -116,8 +116,8 @@ base_repo_finish_installer_template_pr() { return $? fi - std_make_temp_file body_file base-repo-installer-template-pr || { - log_error "Failed to create a temporary pull request body file." + base_std_make_temp_file body_file base-repo-installer-template-pr || { + base_std_log_error "Failed to create a temporary pull request body file." return 1 } base_repo_create_installer_template_pr_body "$target_path" "$repo" "$issue" "$category" > "$body_file" @@ -220,8 +220,8 @@ base_repo_installer_template() { shift ;; -v) - set_log_level DEBUG - export LOG_DEBUG=1 + base_std_set_log_level DEBUG + export BASE_BASH_LIBS_LOG_DEBUG=1 shift ;; -*) @@ -290,7 +290,7 @@ base_repo_installer_template() { else base_repo_require_pr_worktree "$root" "repo installer-template --pr" || return 1 rel_path="$(base_repo_relative_path_under_root "$root" "$path")" || { - log_error "repo installer-template --pr expects path to be inside '$root'." + base_std_log_error "repo installer-template --pr expects path to be inside '$root'." return 1 } issue_category="$(base_repo_pr_issue_category "$github_repo" "$issue")" || return 1 @@ -301,7 +301,7 @@ base_repo_installer_template() { pr_category="$issue_category" fi pr_branch="$(base_repo_pr_branch_name "$pr_category" "$issue" "installer-template" "$repo_name")" || { - log_error "Unable to generate the canonical issue branch for repo installer-template --pr." + base_std_log_error "Unable to generate the canonical issue branch for repo installer-template --pr." return 1 } if [[ "$dry_run" == "1" ]]; then diff --git a/cli/bash/commands/basectl/subcommands/run.sh b/cli/bash/commands/basectl/subcommands/run.sh index 9acefee2..5e71dd17 100644 --- a/cli/bash/commands/basectl/subcommands/run.sh +++ b/cli/bash/commands/basectl/subcommands/run.sh @@ -32,7 +32,7 @@ EOF base_run_usage_error() { base_run_subcommand_usage >&2 - print_error "$*" + base_std_print_error "$*" return 2 } @@ -66,7 +66,7 @@ base_run_list_commands() { local list_output local printed_header=0 - [[ -x "$wrapper" ]] || fatal_error "Base Python wrapper '$wrapper' is missing or is not executable." + [[ -x "$wrapper" ]] || base_std_fatal_error "Base Python wrapper '$wrapper' is missing or is not executable." if [[ -n "$explicit_project" ]]; then command_args+=(--project "$explicit_project") elif [[ -n "$project" ]]; then @@ -203,7 +203,7 @@ base_run_subcommand_main() { fi wrapper="$BASE_HOME/bin/base-wrapper" - [[ -x "$wrapper" ]] || fatal_error "Base Python wrapper '$wrapper' is missing or is not executable." + [[ -x "$wrapper" ]] || base_std_fatal_error "Base Python wrapper '$wrapper' is missing or is not executable." local command_args=(run-command) if [[ -n "$explicit_project" ]]; then @@ -214,7 +214,7 @@ base_run_subcommand_main() { fi resolve_output="$("$wrapper" --project base base_projects "${command_args[@]}" "${args[@]}" --format command-protocol)" || return $? base_command_protocol_decode_one project-command "$resolve_output" || { - fatal_error "Unable to resolve command '$command_name' for project '${explicit_project:-current project}'." + base_std_fatal_error "Unable to resolve command '$command_name' for project '${explicit_project:-current project}'." } resolved_name="${BASE_COMMAND_PROTOCOL_FIELDS[project_name]}" project_root="${BASE_COMMAND_PROTOCOL_FIELDS[project_root]}" @@ -227,7 +227,7 @@ base_run_subcommand_main() { command_runner="${BASE_COMMAND_PROTOCOL_FIELDS[runner]}" [[ -n "$resolved_name" && -n "$project_root" && -n "$manifest_path" && -n "$run_command" ]] || { - fatal_error "Unable to resolve command '$command_name' for project '${explicit_project:-current project}'." + base_std_fatal_error "Unable to resolve command '$command_name' for project '${explicit_project:-current project}'." } command_runner="${command_runner:-}" @@ -244,7 +244,7 @@ base_run_subcommand_main() { base_project_activate_environment \ "$resolved_name" "$project_root" "$manifest_path" "$dry_run" "$route_venv_dir" "$uses_uv_manager" >/dev/null - log_info "Running command '$command_name' for project '$resolved_name': $display_command" + base_std_log_info "Running command '$command_name' for project '$resolved_name': $display_command" base_validate_command_runner "$command_runner" base_project_run_shell_command "$project_root" "$command_to_run" basectl-run "${extra_args[@]}" } diff --git a/cli/bash/commands/basectl/subcommands/setup.sh b/cli/bash/commands/basectl/subcommands/setup.sh index 74e6d75e..abae23bb 100644 --- a/cli/bash/commands/basectl/subcommands/setup.sh +++ b/cli/bash/commands/basectl/subcommands/setup.sh @@ -60,7 +60,7 @@ EOF } base_setup_usage_error() { - print_error "$*" + base_std_print_error "$*" printf "Run 'basectl setup --help' for usage.\n" >&2 return 2 } @@ -72,7 +72,7 @@ base_setup_print_ci_json() { local python_bin python_bin="$(setup_diagnostics_python_bin)" || - fatal_error "Python is required to render Base CI setup JSON." + base_std_fatal_error "Python is required to render Base CI setup JSON." setup_ensure_cached_paths env BASE_HOME="$BASE_HOME" PYTHONPATH="$_BASE_SETUP_PYTHONPATH_CACHE" \ "$python_bin" -m base_setup.ci_json setup-json \ @@ -87,7 +87,7 @@ base_setup_run_text() { BASE_SETUP_START_TIME="$(setup_epoch_seconds)" || BASE_SETUP_START_TIME=0 export BASE_SETUP_START_TIME - log_debug "Running 'basectl setup' (DRY_RUN=$(setup_is_dry_run && printf true || printf false))." + base_std_log_debug "Running 'basectl setup' (BASE_BASH_LIBS_DRY_RUN=$(setup_is_dry_run && printf true || printf false))." if setup_notifications_enabled; then trap 'setup_notify_completion "$?"' EXIT fi @@ -107,8 +107,8 @@ base_setup_run_ci_json() { local exit_code local render_status - std_make_temp_file stdout_file base-ci-setup-stdout || return 1 - std_make_temp_file stderr_file base-ci-setup-stderr || return 1 + base_std_make_temp_file stdout_file base-ci-setup-stdout || return 1 + base_std_make_temp_file stderr_file base-ci-setup-stderr || return 1 base_setup_run_text > "$stdout_file" 2> "$stderr_file" exit_code=$? diff --git a/cli/bash/commands/basectl/subcommands/setup_check_results.sh b/cli/bash/commands/basectl/subcommands/setup_check_results.sh index 902bd00c..0b7e6f8e 100644 --- a/cli/bash/commands/basectl/subcommands/setup_check_results.sh +++ b/cli/bash/commands/basectl/subcommands/setup_check_results.sh @@ -42,7 +42,7 @@ setup_add_check_result_with_status() { ok=false ;; *) - fatal_error "Invalid Base check status '$status'." + base_std_fatal_error "Invalid Base check status '$status'." ;; esac @@ -92,7 +92,7 @@ setup_write_check_result_file() { setup_parse_check_result_file() { local line path="$1" - [[ -f "$path" ]] || fatal_error "Base check probe did not produce result file '$path'." + [[ -f "$path" ]] || base_std_fatal_error "Base check probe did not produce result file '$path'." _BASE_SETUP_PARSED_CHECK_NAME="" _BASE_SETUP_PARSED_CHECK_OK="" @@ -124,12 +124,12 @@ setup_parse_check_result_file() { esac done <"$path" - [[ -n "$_BASE_SETUP_PARSED_CHECK_NAME" ]] || fatal_error "Base check probe result '$path' is missing a name." + [[ -n "$_BASE_SETUP_PARSED_CHECK_NAME" ]] || base_std_fatal_error "Base check probe result '$path' is missing a name." case "$_BASE_SETUP_PARSED_CHECK_OK" in true|false) ;; *) - fatal_error "Base check probe result '$path' has invalid ok value '$_BASE_SETUP_PARSED_CHECK_OK'." + base_std_fatal_error "Base check probe result '$path' has invalid ok value '$_BASE_SETUP_PARSED_CHECK_OK'." ;; esac if [[ -z "$_BASE_SETUP_PARSED_CHECK_STATUS" ]]; then @@ -139,10 +139,10 @@ setup_parse_check_result_file() { ok|warn|error) ;; *) - fatal_error "Base check probe result '$path' has invalid status value '$_BASE_SETUP_PARSED_CHECK_STATUS'." + base_std_fatal_error "Base check probe result '$path' has invalid status value '$_BASE_SETUP_PARSED_CHECK_STATUS'." ;; esac - [[ -n "$_BASE_SETUP_PARSED_CHECK_MESSAGE" ]] || fatal_error "Base check probe result '$path' is missing a message." + [[ -n "$_BASE_SETUP_PARSED_CHECK_MESSAGE" ]] || base_std_fatal_error "Base check probe result '$path' is missing a message." } setup_add_parsed_check_result() { diff --git a/cli/bash/commands/basectl/subcommands/setup_common.sh b/cli/bash/commands/basectl/subcommands/setup_common.sh index c19d1c25..4ba86e43 100644 --- a/cli/bash/commands/basectl/subcommands/setup_common.sh +++ b/cli/bash/commands/basectl/subcommands/setup_common.sh @@ -57,17 +57,17 @@ setup_ensure_cached_paths() { setup_clear_run_state() { # Clear legacy lowercase state too so inherited environments cannot trigger # lib_std.sh dry-run behavior unless this command explicitly enables it. - unset dry_run DRY_RUN BASE_SETUP_CHECK_STATUS_FILE BASE_SETUP_PROFILE_ERROR BASE_SETUP_PROFILES BASE_SETUP_PROJECT_NAME BASE_SETUP_MANIFEST BASE_SETUP_REMOTE_NETWORK BASE_SETUP_RECREATE_VENV BASE_SETUP_UPGRADE_PIP BASE_SETUP_YES + unset BASE_BASH_LIBS_DRY_RUN BASE_SETUP_CHECK_STATUS_FILE BASE_SETUP_PROFILE_ERROR BASE_SETUP_PROFILES BASE_SETUP_PROJECT_NAME BASE_SETUP_MANIFEST BASE_SETUP_REMOTE_NETWORK BASE_SETUP_RECREATE_VENV BASE_SETUP_UPGRADE_PIP BASE_SETUP_YES setup_refresh_cached_paths } setup_enable_dry_run() { - export DRY_RUN=true + export BASE_BASH_LIBS_DRY_RUN=true } setup_enable_debug_logging() { - set_log_level DEBUG - export LOG_DEBUG=1 + base_std_set_log_level DEBUG + export BASE_BASH_LIBS_LOG_DEBUG=1 } setup_epoch_seconds() { @@ -79,7 +79,7 @@ setup_backup_timestamp() { } setup_is_dry_run() { - [[ "${DRY_RUN-}" == true ]] + [[ "${BASE_BASH_LIBS_DRY_RUN-}" == true ]] } setup_enable_yes() { @@ -104,7 +104,7 @@ setup_test_confirm_response() { setup_interactive_consent_available() { setup_test_assume_interactive && return 0 - is_interactive + base_std_is_interactive } setup_read_confirmation_response() { @@ -130,22 +130,22 @@ setup_require_linux_debian_system_consent() { setup_yes_enabled && return 0 if ! setup_interactive_consent_available; then - fatal_error "$reason Run 'basectl setup --dry-run' to review the apt commands, then rerun with '--yes' to apply them." + base_std_fatal_error "$reason Run 'basectl setup --dry-run' to review the apt commands, then rerun with '--yes' to apply them." fi - log_info "$reason" + base_std_log_info "$reason" if [[ -n "${BASE_SETUP_TEST_STATE_DIR:-}" ]]; then setup_allow_test_hooks && touch "$BASE_SETUP_TEST_STATE_DIR/linux-consent-prompted" fi printf "Proceed with Ubuntu/Debian setup changes? [y/N] " >&2 - response="$(setup_read_confirmation_response)" || fatal_error "Ubuntu/Debian setup was not approved." + response="$(setup_read_confirmation_response)" || base_std_fatal_error "Ubuntu/Debian setup was not approved." case "${response,,}" in y|yes) setup_enable_yes return 0 ;; *) - fatal_error "Ubuntu/Debian setup was not approved." + base_std_fatal_error "Ubuntu/Debian setup was not approved." ;; esac } @@ -273,7 +273,7 @@ setup_reject_test_hook_if_disallowed() { local variable_name="$1" setup_allow_test_hooks && return 0 - fatal_error "$variable_name is a test-only setup override. Set BASE_TEST_MODE=true or CI=true to use it." + base_std_fatal_error "$variable_name is a test-only setup override. Set BASE_TEST_MODE=true or CI=true to use it." } setup_recovery_base_bash_libraries() { @@ -296,7 +296,7 @@ setup_notify_completion() { [[ "$OSTYPE" == darwin* ]] || return 0 if ! command -v osascript >/dev/null 2>&1; then if setup_notifications_forced; then - log_warn "Setup notification was requested, but 'osascript' is not available on this Mac." + base_std_log_warn "Setup notification was requested, but 'osascript' is not available on this Mac." fi return 0 fi @@ -398,31 +398,31 @@ setup_print_runtime_chain_summary() { venv_dir="$(setup_venv_dir)" python_bin="$venv_dir/bin/python" - log_info "Runtime chain: BASE_OS=${BASE_OS:-unknown} BASE_PLATFORM=$platform BASE_HOST_ENV=$host_env BASE_HOST=${BASE_HOST:-unknown}" - log_info "Shell: path=${shell_path:-unknown} version=${BASH_VERSION:-unknown} machine=${shell_machine:-unknown} translated=${translated:-unknown}" + base_std_log_info "Runtime chain: BASE_OS=${BASE_OS:-unknown} BASE_PLATFORM=$platform BASE_HOST_ENV=$host_env BASE_HOST=${BASE_HOST:-unknown}" + base_std_log_info "Shell: path=${shell_path:-unknown} version=${BASH_VERSION:-unknown} machine=${shell_machine:-unknown} translated=${translated:-unknown}" if [[ -x "$python_bin" ]]; then pyvenv_cfg="$venv_dir/pyvenv.cfg" python_arch="$(setup_python_machine "$python_bin" 2>/dev/null || setup_executable_architecture "$python_bin" 2>/dev/null || true)" home_path="$(setup_pyvenv_cfg_value home "$pyvenv_cfg" 2>/dev/null || true)" - log_info "Python: path=$python_bin machine=${python_arch:-unknown} home=${home_path:-unknown}" + base_std_log_info "Python: path=$python_bin machine=${python_arch:-unknown} home=${home_path:-unknown}" else - log_info "Python: path=$python_bin status=missing" + base_std_log_info "Python: path=$python_bin status=missing" fi if [[ "$platform" == macos ]]; then if brew_bin="$(setup_find_brew_bin 2>/dev/null)"; then brew_prefix="$(setup_homebrew_prefix 2>/dev/null || true)" - log_info "Homebrew: path=$brew_bin prefix=${brew_prefix:-unknown}" + base_std_log_info "Homebrew: path=$brew_bin prefix=${brew_prefix:-unknown}" else - log_info "Homebrew: status=missing" + base_std_log_info "Homebrew: status=missing" fi fi if gh_bin="$(setup_command_path gh 2>/dev/null)"; then gh_version="$(setup_gh_version_line 2>/dev/null || true)" gh_arch="$(setup_executable_architecture "$gh_bin" 2>/dev/null || true)" - log_info "GitHub CLI: path=$gh_bin version=${gh_version:-unknown} arch=${gh_arch:-unknown}" + base_std_log_info "GitHub CLI: path=$gh_bin version=${gh_version:-unknown} arch=${gh_arch:-unknown}" fi } @@ -768,34 +768,34 @@ setup_seed_user_config() { fi if setup_is_dry_run; then - log_info "[DRY-RUN] Would create Base user config at '$config_path'." + base_std_log_info "[DRY-RUN] Would create Base user config at '$config_path'." return 0 fi config_dir="$(dirname "$config_path")" - safe_mkdir -p "$config_dir" + base_std_safe_mkdir -p "$config_dir" if [[ -e "$config_path" || -L "$config_path" ]]; then return 0 fi temp_file="$(mktemp "$config_path.XXXXXX")" || - fatal_error "Unable to create temporary Base user config for '$config_path'." + base_std_fatal_error "Unable to create temporary Base user config for '$config_path'." { printf 'workspace:\n' printf ' root: ~/work\n' } > "$temp_file" || { rm -f -- "$temp_file" - fatal_error "Unable to write Base user config '$config_path'." + base_std_fatal_error "Unable to write Base user config '$config_path'." } mv -n -- "$temp_file" "$config_path" || { rm -f -- "$temp_file" - fatal_error "Unable to create Base user config '$config_path'." + base_std_fatal_error "Unable to create Base user config '$config_path'." } if [[ -e "$temp_file" ]]; then rm -f -- "$temp_file" return 0 fi - log_info "Created Base user config at '$config_path'." + base_std_log_info "Created Base user config at '$config_path'." } setup_project_venv_python_bin() { @@ -938,7 +938,7 @@ setup_run_project_pre_venv_layer() { setup_ensure_cached_paths venv_dir="$_BASE_SETUP_VENV_DIR_CACHE" - python_bin="$(setup_base_venv_python_bin "$venv_dir")" || fatal_error "Base virtual environment Python was not found at '$venv_dir/bin/python'. $(setup_recovery_venv)" + python_bin="$(setup_base_venv_python_bin "$venv_dir")" || base_std_fatal_error "Base virtual environment Python was not found at '$venv_dir/bin/python'. $(setup_recovery_venv)" args+=(--manifest "$manifest_path") args+=(--action "$action") @@ -973,13 +973,13 @@ setup_run_project_bootstrap_layer() { local project_env_args=() if setup_is_dry_run && ! setup_base_python_package_installed "$(setup_pyyaml_package)"; then - log_info "[DRY-RUN] Would bootstrap project Python runtime after PyYAML is installed." + base_std_log_info "[DRY-RUN] Would bootstrap project Python runtime after PyYAML is installed." return 0 fi setup_ensure_cached_paths venv_dir="$_BASE_SETUP_VENV_DIR_CACHE" - python_bin="$(setup_base_venv_python_bin "$venv_dir")" || fatal_error "Base virtual environment Python was not found at '$venv_dir/bin/python'. $(setup_recovery_venv)" + python_bin="$(setup_base_venv_python_bin "$venv_dir")" || base_std_fatal_error "Base virtual environment Python was not found at '$venv_dir/bin/python'. $(setup_recovery_venv)" if setup_is_dry_run; then args+=(--dry-run) @@ -987,7 +987,7 @@ setup_run_project_bootstrap_layer() { args+=(--manifest "$manifest_path" --action bootstrap "$project") if [[ "$output_format" != json ]]; then - log_info "Bootstrapping Python runtime for project '$project'." + base_std_log_info "Bootstrapping Python runtime for project '$project'." fi setup_ensure_cached_paths @@ -1029,7 +1029,7 @@ setup_run_project_artifact_layer() { local project_env_args=() if setup_is_dry_run && ! setup_base_python_package_installed "$(setup_pyyaml_package)"; then - log_info "[DRY-RUN] Would run Python project setup layer after PyYAML is installed." + base_std_log_info "[DRY-RUN] Would run Python project setup layer after PyYAML is installed." return 0 fi @@ -1037,31 +1037,31 @@ setup_run_project_artifact_layer() { requested_project="$project" setup_ensure_cached_paths venv_dir="$_BASE_SETUP_VENV_DIR_CACHE" - python_bin="$(setup_base_venv_python_bin "$venv_dir")" || fatal_error "Base virtual environment Python was not found at '$venv_dir/bin/python'. $(setup_recovery_venv)" + python_bin="$(setup_base_venv_python_bin "$venv_dir")" || base_std_fatal_error "Base virtual environment Python was not found at '$venv_dir/bin/python'. $(setup_recovery_venv)" setup_resolve_project_manifest "$project" "$python_bin" project resolved_root manifest_path || { if [[ -z "$requested_project" && -n "${BASE_SETUP_MANIFEST:-}" ]]; then - log_error "Unable to resolve a project from manifest '$BASE_SETUP_MANIFEST'." + base_std_log_error "Unable to resolve a project from manifest '$BASE_SETUP_MANIFEST'." else - log_error "Unable to resolve Base project '$project'." - log_error "Run 'basectl projects list' to see projects Base can discover." + base_std_log_error "Unable to resolve Base project '$project'." + base_std_log_error "Run 'basectl projects list' to see projects Base can discover." fi return 1 } if [[ "$project" != base ]]; then if [[ "$output_format" != json ]]; then if [[ "$action" == setup ]]; then - log_info "Resolved project '$project' at '$resolved_root'." + base_std_log_info "Resolved project '$project' at '$resolved_root'." else - log_debug "Resolved project '$project' at '$resolved_root'." + base_std_log_debug "Resolved project '$project' at '$resolved_root'." fi fi fi route_output="$(setup_resolve_project_route "$project" "$manifest_path" "$python_bin")" || { - log_error "Unable to resolve Base project environment for '$project'." + base_std_log_error "Unable to resolve Base project environment for '$project'." return 1 } base_command_protocol_decode_one project-setup-route "$route_output" || { - log_error "Python project routing returned invalid metadata for '$project'." + base_std_log_error "Python project routing returned invalid metadata for '$project'." return 1 } project="${BASE_COMMAND_PROTOCOL_FIELDS[project_name]}" @@ -1074,17 +1074,17 @@ setup_run_project_artifact_layer() { project_uses_uv_manager="${BASE_COMMAND_PROTOCOL_FIELDS[uses_uv_manager]}" project_requires_python="${BASE_COMMAND_PROTOCOL_FIELDS[requires_project_python]}" if [[ -z "$project" || -z "$resolved_root" || -z "$manifest_path" || -z "$project_venv_dir" ]]; then - log_error "Python project routing returned incomplete metadata for '$project'." + base_std_log_error "Python project routing returned incomplete metadata for '$project'." return 1 fi BASE_SETUP_PROJECT_NAME="$project" export BASE_SETUP_PROJECT_NAME if [[ "$project_uses_uv_manager" != true && "$project_uses_uv_manager" != false ]]; then - log_error "Python project routing returned invalid uv-manager metadata for '$project'." + base_std_log_error "Python project routing returned invalid uv-manager metadata for '$project'." return 1 fi if [[ "$project_requires_python" != true && "$project_requires_python" != false ]]; then - log_error "Python project routing returned invalid project-Python metadata for '$project'." + base_std_log_error "Python project routing returned invalid project-Python metadata for '$project'." return 1 fi if [[ "$project" == base ]]; then @@ -1114,9 +1114,9 @@ setup_run_project_artifact_layer() { if [[ "$output_format" != json ]]; then if [[ "$action" == setup ]]; then - log_info "Running Python project $action layer." + base_std_log_info "Running Python project $action layer." else - log_debug "Running Python project $action layer." + base_std_log_debug "Running Python project $action layer." fi fi @@ -1124,25 +1124,25 @@ setup_run_project_artifact_layer() { setup_run_project_bootstrap_layer "$manifest_path" "$project" "$output_format" "$resolved_root" "$project_venv_dir" exit_code=$? if ((exit_code)); then - log_error "$(setup_recovery_project_layer)" - log_error "Python project $action layer failed." + base_std_log_error "$(setup_recovery_project_layer)" + base_std_log_error "Python project $action layer failed." return "$exit_code" fi fi if [[ "$action" == setup ]] && setup_upgrade_pip_enabled && [[ "$project" != base ]]; then if [[ "$project_uses_uv_manager" == true ]]; then - log_warn "Skipping pip upgrade for project '$project': its virtual environment is managed by uv. Run 'uv sync' to reconcile the project environment." + base_std_log_warn "Skipping pip upgrade for project '$project': its virtual environment is managed by uv. Run 'uv sync' to reconcile the project environment." elif [[ "$project_requires_python" == true ]]; then setup_upgrade_project_pip "$project" "$project_venv_dir" || return $? else - log_warn "Skipping pip upgrade for project '$project': it does not declare a Python runtime." + base_std_log_warn "Skipping pip upgrade for project '$project': it does not declare a Python runtime." fi fi if [[ "$project_requires_python" == true && "$project_uses_uv_manager" != true ]] && ! setup_virtualenv_healthy_path "$project_venv_dir"; then if setup_is_dry_run && [[ "$action" == setup ]]; then - log_info "[DRY-RUN] Would run Python project setup layer through base-wrapper for project '$project'." + base_std_log_info "[DRY-RUN] Would run Python project setup layer through base-wrapper for project '$project'." return 0 fi if [[ "$output_format" == json ]]; then @@ -1174,11 +1174,11 @@ setup_run_project_artifact_layer() { "$(setup_recovery_project_venv "$project" "$resolved_root" "$project_venv_dir")" elif [[ "$action" == check ]]; then setup_run_project_pre_venv_layer precheck text "$manifest_path" "$project" "$resolved_root" "$project_venv_dir" "$remote_network" || true - log_error "$_BASE_SETUP_VENV_HEALTH_MESSAGE" - log_error "$(setup_recovery_project_venv "$project" "$resolved_root" "$project_venv_dir")" + base_std_log_error "$_BASE_SETUP_VENV_HEALTH_MESSAGE" + base_std_log_error "$(setup_recovery_project_venv "$project" "$resolved_root" "$project_venv_dir")" else - log_warn "$_BASE_SETUP_VENV_HEALTH_MESSAGE" - log_warn "$(setup_recovery_project_venv "$project" "$resolved_root" "$project_venv_dir")" + base_std_log_warn "$_BASE_SETUP_VENV_HEALTH_MESSAGE" + base_std_log_warn "$(setup_recovery_project_venv "$project" "$resolved_root" "$project_venv_dir")" fi return 1 fi @@ -1205,12 +1205,12 @@ setup_run_project_artifact_layer() { exit_code=$? if ((exit_code)) && [[ "$action" == setup ]]; then - log_error "$(setup_recovery_project_layer)" - log_error "Python project $action layer failed." + base_std_log_error "$(setup_recovery_project_layer)" + base_std_log_error "Python project $action layer failed." return "$exit_code" fi if ((exit_code)) && [[ "$action" == check ]]; then - log_error "Python project check layer found missing requirements." + base_std_log_error "Python project check layer found missing requirements." return "$exit_code" fi if ((exit_code)); then @@ -1265,7 +1265,7 @@ setup_collect_platform_base_check_results() { setup_collect_linux_debian_base_check_results "$@" ;; *) - fatal_error "$(setup_unsupported_platform_message "$platform")" + base_std_fatal_error "$(setup_unsupported_platform_message "$platform")" ;; esac } @@ -1288,25 +1288,25 @@ setup_print_check_text_results() { status="${_BASE_SETUP_CHECK_STATUSES[$i]:-$(setup_diagnostic_status_from_ok "${_BASE_SETUP_CHECK_OK[$i]}")}" case "$status" in ok) - log_info "${_BASE_SETUP_CHECK_MESSAGES[$i]}" + base_std_log_info "${_BASE_SETUP_CHECK_MESSAGES[$i]}" if [[ -n "${_BASE_SETUP_CHECK_DEBUG_MESSAGES[$i]}" ]]; then - log_debug "${_BASE_SETUP_CHECK_DEBUG_MESSAGES[$i]}" + base_std_log_debug "${_BASE_SETUP_CHECK_DEBUG_MESSAGES[$i]}" fi ;; warn) - log_warn "${_BASE_SETUP_CHECK_MESSAGES[$i]}" + base_std_log_warn "${_BASE_SETUP_CHECK_MESSAGES[$i]}" if [[ -n "${_BASE_SETUP_CHECK_RECOVERIES[$i]}" ]]; then - log_warn "${_BASE_SETUP_CHECK_RECOVERIES[$i]}" + base_std_log_warn "${_BASE_SETUP_CHECK_RECOVERIES[$i]}" fi ;; error) - log_error "${_BASE_SETUP_CHECK_MESSAGES[$i]}" + base_std_log_error "${_BASE_SETUP_CHECK_MESSAGES[$i]}" if [[ -n "${_BASE_SETUP_CHECK_RECOVERIES[$i]}" ]]; then - log_error "${_BASE_SETUP_CHECK_RECOVERIES[$i]}" + base_std_log_error "${_BASE_SETUP_CHECK_RECOVERIES[$i]}" fi ;; *) - fatal_error "Invalid Base check status '$status'." + base_std_fatal_error "Invalid Base check status '$status'." ;; esac done @@ -1339,7 +1339,7 @@ setup_check_result_recovery() { setup_write_collected_check_result_files() { local count i output_dir="$1" output_path - mkdir -p -- "$output_dir" || fatal_error "Unable to create Base check result directory '$output_dir'." + mkdir -p -- "$output_dir" || base_std_fatal_error "Unable to create Base check result directory '$output_dir'." count="${#_BASE_SETUP_CHECK_NAMES[@]}" for ((i = 0; i < count; i++)); do @@ -1369,8 +1369,8 @@ setup_run_check() { aggregate_status="$(setup_check_results_status)" if setup_profiles_enabled; then - std_make_temp_file profile_status_file base-profile-check-status || - fatal_error "Unable to create temporary profile check status file." + base_std_make_temp_file profile_status_file base-profile-check-status || + base_std_fatal_error "Unable to create temporary profile check status file." BASE_SETUP_CHECK_STATUS_FILE="$profile_status_file" export BASE_SETUP_CHECK_STATUS_FILE if ! setup_run_base_dev_layer check; then @@ -1379,7 +1379,7 @@ setup_run_check() { elif layer_status="$(setup_read_published_check_status "$profile_status_file")"; then aggregate_status="$(setup_merge_diagnostic_status "$aggregate_status" "$layer_status")" else - log_error "Python prerequisite profile check layer did not report a valid aggregate status." + base_std_log_error "Python prerequisite profile check layer did not report a valid aggregate status." missing=1 aggregate_status="error" fi @@ -1387,8 +1387,8 @@ setup_run_check() { fi if [[ -n "$project" || -n "${BASE_SETUP_MANIFEST:-}" ]]; then - std_make_temp_file project_status_file base-project-check-status || - fatal_error "Unable to create temporary project check status file." + base_std_make_temp_file project_status_file base-project-check-status || + base_std_fatal_error "Unable to create temporary project check status file." BASE_SETUP_CHECK_STATUS_FILE="$project_status_file" export BASE_SETUP_CHECK_STATUS_FILE if ! setup_run_project_artifact_check; then @@ -1397,7 +1397,7 @@ setup_run_check() { elif layer_status="$(setup_read_published_check_status "$project_status_file")"; then aggregate_status="$(setup_merge_diagnostic_status "$aggregate_status" "$layer_status")" else - log_error "Python project check layer did not report a valid aggregate status." + base_std_log_error "Python project check layer did not report a valid aggregate status." missing=1 aggregate_status="error" fi @@ -1408,20 +1408,20 @@ setup_run_check() { if ((missing == 0)) && [[ "$aggregate_status" != error ]]; then setup_record_project_check_result "$project" "$aggregate_status" if [[ -n "$project" ]]; then - log_info "Base CLI environment and project '$project' check passed." + base_std_log_info "Base CLI environment and project '$project' check passed." else - log_info "Base CLI environment check passed." + base_std_log_info "Base CLI environment check passed." fi return 0 fi setup_record_project_check_result "$project" error if [[ -n "$project" ]]; then - log_error "Base CLI environment or project '$project' check found missing requirements." - log_error "Review the specific Fix lines above and rerun 'basectl check $project' after resolving the missing requirements." + base_std_log_error "Base CLI environment or project '$project' check found missing requirements." + base_std_log_error "Review the specific Fix lines above and rerun 'basectl check $project' after resolving the missing requirements." else - log_error "Base CLI environment check found missing requirements." - log_error "Review the specific Fix lines above and rerun 'basectl check' after resolving the missing requirements." + base_std_log_error "Base CLI environment check found missing requirements." + base_std_log_error "Review the specific Fix lines above and rerun 'basectl check' after resolving the missing requirements." fi return 1 } @@ -1445,8 +1445,8 @@ setup_run_check_json() { local remote_network="${1:-${BASE_SETUP_REMOTE_NETWORK:-}}" setup_collect_base_check_results warn || true - std_make_temp_dir check_result_dir base-check-json || - fatal_error "Unable to create temporary Base check JSON result directory." + base_std_make_temp_dir check_result_dir base-check-json || + base_std_fatal_error "Unable to create temporary Base check JSON result directory." if setup_profiles_enabled; then if ! profile_json="$(setup_run_base_dev_layer check --format json)"; then @@ -1502,7 +1502,7 @@ setup_run_platform_install() { setup_run_linux_debian_install ;; *) - fatal_error "$(setup_unsupported_install_platform_message "$platform")" + base_std_fatal_error "$(setup_unsupported_install_platform_message "$platform")" ;; esac } diff --git a/cli/bash/commands/basectl/subcommands/setup_diagnostics_fallback.sh b/cli/bash/commands/basectl/subcommands/setup_diagnostics_fallback.sh index 28633b88..f76b9184 100644 --- a/cli/bash/commands/basectl/subcommands/setup_diagnostics_fallback.sh +++ b/cli/bash/commands/basectl/subcommands/setup_diagnostics_fallback.sh @@ -87,17 +87,17 @@ setup_diagnostics_fallback_record_check() { shift 2 ;; *) - fatal_error "Unsupported diagnostics fallback argument '$1'." + base_std_fatal_error "Unsupported diagnostics fallback argument '$1'." ;; esac done case "$status" in ok|warn|error) ;; - *) fatal_error "Invalid diagnostics record status '$status'." ;; + *) base_std_fatal_error "Invalid diagnostics record status '$status'." ;; esac [[ -n "$project" && -n "$checked_at" && -n "$path" ]] || - fatal_error "Diagnostics record fallback requires project, status, checked-at, and output-path." + base_std_fatal_error "Diagnostics record fallback requires project, status, checked-at, and output-path." mkdir -p -- "$(dirname -- "$path")" || return 1 tmp_path="${path}.tmp.$$" @@ -146,7 +146,7 @@ setup_diagnostics_fallback_json() { shift 2 ;; *) - fatal_error "Unsupported diagnostics fallback argument '$1'." + base_std_fatal_error "Unsupported diagnostics fallback argument '$1'." ;; esac done @@ -205,7 +205,7 @@ setup_diagnostics_fallback_json() { shift 2 ;; *) - fatal_error "Unsupported diagnostics fallback argument '$1'." + base_std_fatal_error "Unsupported diagnostics fallback argument '$1'." ;; esac done @@ -259,7 +259,7 @@ setup_diagnostics_fallback_json() { return $? ;; *) - fatal_error "Python is required to render diagnostics command '$command'." + base_std_fatal_error "Python is required to render diagnostics command '$command'." ;; esac } diff --git a/cli/bash/commands/basectl/subcommands/setup_linux_debian.sh b/cli/bash/commands/basectl/subcommands/setup_linux_debian.sh index 935e1514..62a1a699 100644 --- a/cli/bash/commands/basectl/subcommands/setup_linux_debian.sh +++ b/cli/bash/commands/basectl/subcommands/setup_linux_debian.sh @@ -158,7 +158,7 @@ setup_add_linux_command_check_result() { warn|error) ;; *) - fatal_error "Invalid Linux command check missing status '$missing_status'." + base_std_fatal_error "Invalid Linux command check missing status '$missing_status'." ;; esac @@ -319,20 +319,20 @@ setup_run_linux_debian_apt_prerequisites() { IFS=' ' read -r -a package_args <<<"$packages" if setup_is_dry_run; then - log_info "[DRY-RUN] Would run: $(setup_linux_debian_apt_update_command)" - log_info "[DRY-RUN] Would run: $(setup_linux_debian_apt_prerequisite_command)" + base_std_log_info "[DRY-RUN] Would run: $(setup_linux_debian_apt_update_command)" + base_std_log_info "[DRY-RUN] Would run: $(setup_linux_debian_apt_prerequisite_command)" return 0 fi if setup_linux_debian_apt_prerequisites_installed "${package_args[@]}"; then - log_info "Ubuntu/Debian apt prerequisites are already installed." + base_std_log_info "Ubuntu/Debian apt prerequisites are already installed." return 0 fi setup_require_linux_debian_system_consent \ "Ubuntu/Debian setup can install apt packages, configure package repositories, and run platform bootstraps." || return $? - log_info "Installing Ubuntu/Debian apt prerequisites." + base_std_log_info "Installing Ubuntu/Debian apt prerequisites." sudo apt-get update || return $? sudo apt-get install -y "${package_args[@]}" || return $? } @@ -343,43 +343,43 @@ setup_run_linux_debian_github_cli_prerequisite() { local source_tmp if setup_linux_command_path gh >/dev/null 2>&1; then - log_info "GitHub CLI 'gh' is already installed; authentication remains user-owned." + base_std_log_info "GitHub CLI 'gh' is already installed; authentication remains user-owned." return 0 fi if setup_is_dry_run; then - log_info "$(setup_linux_debian_github_cli_install_guidance)" - log_info "[DRY-RUN] Would run: sudo install -d -m 0755 /etc/apt/keyrings" - log_info "[DRY-RUN] Would fetch: $(setup_linux_debian_github_cli_keyring_url)" - log_info "[DRY-RUN] Would run: sudo install -m 0644 $(setup_linux_debian_github_cli_keyring_path)" - log_info "[DRY-RUN] Would run: sudo install -d -m 0755 /etc/apt/sources.list.d" - log_info "[DRY-RUN] Would write apt source: $(setup_linux_debian_github_cli_source_line)" - log_info "[DRY-RUN] Would run: sudo apt-get update" - log_info "[DRY-RUN] Would run: sudo apt-get install -y gh" + base_std_log_info "$(setup_linux_debian_github_cli_install_guidance)" + base_std_log_info "[DRY-RUN] Would run: sudo install -d -m 0755 /etc/apt/keyrings" + base_std_log_info "[DRY-RUN] Would fetch: $(setup_linux_debian_github_cli_keyring_url)" + base_std_log_info "[DRY-RUN] Would run: sudo install -m 0644 $(setup_linux_debian_github_cli_keyring_path)" + base_std_log_info "[DRY-RUN] Would run: sudo install -d -m 0755 /etc/apt/sources.list.d" + base_std_log_info "[DRY-RUN] Would write apt source: $(setup_linux_debian_github_cli_source_line)" + base_std_log_info "[DRY-RUN] Would run: sudo apt-get update" + base_std_log_info "[DRY-RUN] Would run: sudo apt-get install -y gh" return 0 fi setup_require_linux_debian_system_consent \ "Ubuntu/Debian setup can install apt packages, configure package repositories, and run platform bootstraps." || return $? - command -v curl >/dev/null 2>&1 || fatal_error "curl is required to install GitHub CLI 'gh' from its official Debian/Ubuntu apt repository." - command -v dpkg >/dev/null 2>&1 || fatal_error "dpkg is required to configure GitHub CLI's official Debian/Ubuntu apt repository." - arch="$(dpkg --print-architecture)" || fatal_error "Unable to read Debian architecture for GitHub CLI apt repository setup." - [[ -n "$arch" ]] || fatal_error "Unable to read Debian architecture for GitHub CLI apt repository setup." + command -v curl >/dev/null 2>&1 || base_std_fatal_error "curl is required to install GitHub CLI 'gh' from its official Debian/Ubuntu apt repository." + command -v dpkg >/dev/null 2>&1 || base_std_fatal_error "dpkg is required to configure GitHub CLI's official Debian/Ubuntu apt repository." + arch="$(dpkg --print-architecture)" || base_std_fatal_error "Unable to read Debian architecture for GitHub CLI apt repository setup." + [[ -n "$arch" ]] || base_std_fatal_error "Unable to read Debian architecture for GitHub CLI apt repository setup." - std_make_temp_file keyring_tmp base-github-cli-keyring || fatal_error "Failed to create a temporary GitHub CLI keyring file." - std_make_temp_file source_tmp base-github-cli-source || { - fatal_error "Failed to create a temporary GitHub CLI apt source file." + base_std_make_temp_file keyring_tmp base-github-cli-keyring || base_std_fatal_error "Failed to create a temporary GitHub CLI keyring file." + base_std_make_temp_file source_tmp base-github-cli-source || { + base_std_fatal_error "Failed to create a temporary GitHub CLI apt source file." } if ! curl -fsSL -o "$keyring_tmp" "$(setup_linux_debian_github_cli_keyring_url)"; then - fatal_error "Failed to download GitHub CLI's official Debian/Ubuntu apt keyring." + base_std_fatal_error "Failed to download GitHub CLI's official Debian/Ubuntu apt keyring." fi setup_linux_debian_github_cli_source_line "$arch" >"$source_tmp" || { - fatal_error "Failed to prepare GitHub CLI apt source configuration." + base_std_fatal_error "Failed to prepare GitHub CLI apt source configuration." } - log_info "Installing GitHub CLI 'gh' from GitHub CLI's official Debian/Ubuntu apt repository." + base_std_log_info "Installing GitHub CLI 'gh' from GitHub CLI's official Debian/Ubuntu apt repository." sudo install -d -m 0755 /etc/apt/keyrings || { return 1 } @@ -408,17 +408,17 @@ setup_run_linux_debian_install() { setup_install_base_cli if setup_profiles_enabled; then if setup_is_dry_run; then - setup_run_base_dev_layer setup --dry-run || fatal_error "Python prerequisite profile layer failed." + setup_run_base_dev_layer setup --dry-run || base_std_fatal_error "Python prerequisite profile layer failed." else - setup_run_base_dev_layer setup || fatal_error "Python prerequisite profile layer failed." + setup_run_base_dev_layer setup || base_std_fatal_error "Python prerequisite profile layer failed." fi fi setup_run_project_artifact_setup || return $? setup_seed_user_config if setup_is_dry_run; then - log_info "[DRY-RUN] Base CLI setup check is complete." + base_std_log_info "[DRY-RUN] Base CLI setup check is complete." else - log_info "Base CLI setup is complete." + base_std_log_info "Base CLI setup is complete." fi } diff --git a/cli/bash/commands/basectl/subcommands/setup_macos_homebrew.sh b/cli/bash/commands/basectl/subcommands/setup_macos_homebrew.sh index 060cef9f..42074c7b 100644 --- a/cli/bash/commands/basectl/subcommands/setup_macos_homebrew.sh +++ b/cli/bash/commands/basectl/subcommands/setup_macos_homebrew.sh @@ -119,7 +119,7 @@ setup_refresh_brew_path() { local brew_bin brew_bin="$(setup_find_brew_bin)" || return 1 - add_to_path -p "$(dirname "$brew_bin")" + base_std_add_to_path -p "$(dirname "$brew_bin")" return 0 } @@ -187,8 +187,8 @@ setup_homebrew_installer_sha256() { } setup_log_homebrew_mutable_policy() { - log_info "Homebrew installer trust policy: using Homebrew's official mutable installer without checksum verification." - log_info "Set BASE_HOMEBREW_INSTALLER_URL and BASE_HOMEBREW_INSTALLER_SHA256 to use a pinned verified installer." + base_std_log_info "Homebrew installer trust policy: using Homebrew's official mutable installer without checksum verification." + base_std_log_info "Set BASE_HOMEBREW_INSTALLER_URL and BASE_HOMEBREW_INSTALLER_SHA256 to use a pinned verified installer." } setup_fetch_homebrew_installer() { @@ -219,28 +219,28 @@ setup_run_verified_homebrew_installer() { local actual_sha256 local exit_code - std_make_temp_file installer_file base-homebrew-installer || fatal_error "Failed to create a temporary Homebrew installer file." + base_std_make_temp_file installer_file base-homebrew-installer || base_std_fatal_error "Failed to create a temporary Homebrew installer file." setup_fetch_homebrew_installer "$installer_url" "$installer_file" || { - fatal_error "Failed to read pinned Homebrew installer content from '$installer_url'." + base_std_fatal_error "Failed to read pinned Homebrew installer content from '$installer_url'." } command -v shasum >/dev/null 2>&1 || { - fatal_error "shasum is required to verify pinned Homebrew installer content." + base_std_fatal_error "shasum is required to verify pinned Homebrew installer content." } checksum="$(shasum -a 256 "$installer_file")" || { - fatal_error "Failed to compute Homebrew installer checksum." + base_std_fatal_error "Failed to compute Homebrew installer checksum." } actual_sha256="${checksum%% *}" if [[ "$actual_sha256" != "$expected_sha256" ]]; then - fatal_error "Homebrew installer checksum mismatch (expected $expected_sha256, got $actual_sha256)." + base_std_fatal_error "Homebrew installer checksum mismatch (expected $expected_sha256, got $actual_sha256)." fi /bin/bash "$installer_file" exit_code=$? if ((exit_code)); then - log_error "$(setup_recovery_homebrew)" + base_std_log_error "$(setup_recovery_homebrew)" fi - exit_if_error "$exit_code" "Homebrew installer failed." + base_std_exit_if_error "$exit_code" "Homebrew installer failed." } setup_install_homebrew() { @@ -256,8 +256,8 @@ setup_install_homebrew() { installer_sha256="$(setup_homebrew_installer_sha256)" if setup_find_brew_bin >/dev/null 2>&1; then - setup_refresh_brew_path || fatal_error "Homebrew is installed, but its bin directory could not be added to PATH. $(setup_recovery_brew_path)" - log_info "Homebrew is already installed." + setup_refresh_brew_path || base_std_fatal_error "Homebrew is installed, but its bin directory could not be added to PATH. $(setup_recovery_brew_path)" + base_std_log_info "Homebrew is already installed." return 0 fi @@ -265,50 +265,50 @@ setup_install_homebrew() { setup_homebrew_pinned_url_selected && setup_homebrew_pinned_sha256_selected && [[ -n "$installer_url" && -n "$installer_sha256" ]] || - fatal_error "Pinned Homebrew installer URL and SHA-256 are both required." - log_info "Installing Homebrew." - log_info "Using pinned Homebrew installer from $installer_url." + base_std_fatal_error "Pinned Homebrew installer URL and SHA-256 are both required." + base_std_log_info "Installing Homebrew." + base_std_log_info "Using pinned Homebrew installer from $installer_url." if setup_is_dry_run; then - log_info "[DRY-RUN] Would verify Homebrew installer SHA-256 $installer_sha256" - log_info "[DRY-RUN] Would run: /bin/bash " + base_std_log_info "[DRY-RUN] Would verify Homebrew installer SHA-256 $installer_sha256" + base_std_log_info "[DRY-RUN] Would run: /bin/bash " return 0 fi setup_run_verified_homebrew_installer "$installer_url" "$installer_sha256" - setup_refresh_brew_path || fatal_error "Homebrew installation finished, but 'brew' was not found on PATH. $(setup_recovery_brew_path)" + setup_refresh_brew_path || base_std_fatal_error "Homebrew installation finished, but 'brew' was not found on PATH. $(setup_recovery_brew_path)" return 0 fi setup_log_homebrew_mutable_policy if setup_is_dry_run; then - log_info "[DRY-RUN] Would run: /bin/bash -c " + base_std_log_info "[DRY-RUN] Would run: /bin/bash -c " return 0 fi - log_info "Installing Homebrew." + base_std_log_info "Installing Homebrew." if [[ -n "${BASE_SETUP_HOMEBREW_INSTALLER_SCRIPT:-}" ]]; then setup_reject_test_hook_if_disallowed BASE_SETUP_HOMEBREW_INSTALLER_SCRIPT "$BASE_SETUP_HOMEBREW_INSTALLER_SCRIPT" exit_code=$? if ((exit_code)); then - log_error "$(setup_recovery_homebrew)" + base_std_log_error "$(setup_recovery_homebrew)" fi - exit_if_error "$exit_code" "Homebrew installation failed." + base_std_exit_if_error "$exit_code" "Homebrew installation failed." else - command -v curl >/dev/null 2>&1 || fatal_error "curl is required to install Homebrew. Install curl or install Homebrew manually from https://brew.sh/, then rerun 'basectl setup'." + command -v curl >/dev/null 2>&1 || base_std_fatal_error "curl is required to install Homebrew. Install curl or install Homebrew manually from https://brew.sh/, then rerun 'basectl setup'." /bin/bash -c "$(curl -fsSL "$installer_url")" exit_code=$? if ((exit_code)); then - log_error "$(setup_recovery_homebrew)" + base_std_log_error "$(setup_recovery_homebrew)" fi - exit_if_error "$exit_code" "Homebrew installation failed." + base_std_exit_if_error "$exit_code" "Homebrew installation failed." fi - setup_refresh_brew_path || fatal_error "Homebrew installation finished, but 'brew' was not found on PATH. $(setup_recovery_brew_path)" + setup_refresh_brew_path || base_std_fatal_error "Homebrew installation finished, but 'brew' was not found on PATH. $(setup_recovery_brew_path)" } setup_require_macos() { - [[ "$OSTYPE" == darwin* ]] || fatal_error "The setup command currently supports macOS only (OSTYPE='$OSTYPE')." + [[ "$OSTYPE" == darwin* ]] || base_std_fatal_error "The setup command currently supports macOS only (OSTYPE='$OSTYPE')." } setup_xcode_tools_installed() { @@ -324,35 +324,35 @@ setup_install_xcode_tools() { local timeout interval start_time current_time if setup_xcode_tools_installed; then - log_info "Xcode Command Line Tools are already installed." + base_std_log_info "Xcode Command Line Tools are already installed." return 0 fi - if ! is_interactive && ! setup_allow_noninteractive_xcode_install && ! setup_is_dry_run; then - fatal_error "Xcode Command Line Tools installation requires an interactive terminal. $(setup_recovery_xcode_tools)" + if ! base_std_is_interactive && ! setup_allow_noninteractive_xcode_install && ! setup_is_dry_run; then + base_std_fatal_error "Xcode Command Line Tools installation requires an interactive terminal. $(setup_recovery_xcode_tools)" fi if setup_is_dry_run; then - log_info "[DRY-RUN] Would install Xcode Command Line Tools and wait for installation to complete." + base_std_log_info "[DRY-RUN] Would install Xcode Command Line Tools and wait for installation to complete." return 0 fi - log_info "Installing Xcode Command Line Tools." + base_std_log_info "Installing Xcode Command Line Tools." xcode-select --install || true timeout="$(setup_xcode_wait_timeout_seconds)" interval="$(setup_xcode_wait_interval_seconds)" - start_time="$(setup_epoch_seconds)" || fatal_error "Unable to read current time while waiting for Xcode Command Line Tools." + start_time="$(setup_epoch_seconds)" || base_std_fatal_error "Unable to read current time while waiting for Xcode Command Line Tools." until setup_xcode_tools_installed; do - current_time="$(setup_epoch_seconds)" || fatal_error "Unable to read current time while waiting for Xcode Command Line Tools." + current_time="$(setup_epoch_seconds)" || base_std_fatal_error "Unable to read current time while waiting for Xcode Command Line Tools." if ((current_time - start_time >= timeout)); then - fatal_error "Timed out waiting for Xcode Command Line Tools installation to complete. If the installer is still open, finish it. Otherwise $(setup_recovery_xcode_tools)" + base_std_fatal_error "Timed out waiting for Xcode Command Line Tools installation to complete. If the installer is still open, finish it. Otherwise $(setup_recovery_xcode_tools)" fi sleep "$interval" done - log_info "Xcode Command Line Tools installation detected." + base_std_log_info "Xcode Command Line Tools installation detected." } setup_python_installed() { @@ -369,19 +369,19 @@ setup_install_python() { formula="$(setup_python_formula)" if setup_python_installed; then - log_info "Python formula '$formula' is already installed via Homebrew." + base_std_log_info "Python formula '$formula' is already installed via Homebrew." return 0 fi if setup_is_dry_run; then - log_info "[DRY-RUN] Would install Python formula '$formula' via Homebrew." + base_std_log_info "[DRY-RUN] Would install Python formula '$formula' via Homebrew." return 0 fi - brew_bin="$(setup_find_brew_bin)" || fatal_error "Homebrew is required to install Python formula '$formula'. $(setup_recovery_homebrew)" + brew_bin="$(setup_find_brew_bin)" || base_std_fatal_error "Homebrew is required to install Python formula '$formula'. $(setup_recovery_homebrew)" - log_info "Installing Python formula '$formula' via Homebrew." - "$brew_bin" install "$formula" || fatal_error "Homebrew failed to install Python formula '$formula'." + base_std_log_info "Installing Python formula '$formula' via Homebrew." + "$brew_bin" install "$formula" || base_std_fatal_error "Homebrew failed to install Python formula '$formula'." } setup_find_python_bin() { @@ -439,7 +439,7 @@ setup_read_homebrew_check_result_file() { setup_parse_check_result_file "$path" [[ "$_BASE_SETUP_PARSED_CHECK_NAME" == homebrew ]] || - fatal_error "Base check probe result '$path' contains unexpected name '$_BASE_SETUP_PARSED_CHECK_NAME'." + base_std_fatal_error "Base check probe result '$path' contains unexpected name '$_BASE_SETUP_PARSED_CHECK_NAME'." if [[ "$_BASE_SETUP_PARSED_CHECK_OK" == true ]]; then if setup_refresh_brew_path; then @@ -447,7 +447,7 @@ setup_read_homebrew_check_result_file() { return 0 fi if [[ "$refresh_brew_failure_mode" == fatal ]]; then - fatal_error "Homebrew is installed, but its bin directory could not be added to PATH. $(setup_recovery_brew_path)" + base_std_fatal_error "Homebrew is installed, but its bin directory could not be added to PATH. $(setup_recovery_brew_path)" fi setup_add_check_result \ "homebrew" \ @@ -544,8 +544,8 @@ setup_collect_macos_base_check_results() { pyyaml_package="$(setup_pyyaml_package)" setup_ensure_cached_paths - std_make_temp_dir tmpdir base-check || - fatal_error "Unable to create temporary directory for Base check probes." + base_std_make_temp_dir tmpdir base-check || + base_std_fatal_error "Unable to create temporary directory for Base check probes." setup_write_homebrew_check_probe "$tmpdir/homebrew" & probe_pids+=("$!") @@ -561,7 +561,7 @@ setup_collect_macos_base_check_results() { probe_pids+=("$!") setup_wait_for_base_check_probes "${probe_pids[@]}" || - fatal_error "One or more Base check probes failed before writing results." + base_std_fatal_error "One or more Base check probes failed before writing results." setup_read_homebrew_check_result_file "$tmpdir/homebrew" "$refresh_brew_failure_mode" || missing=1 setup_add_base_bash_libraries_check_result @@ -587,17 +587,17 @@ setup_run_macos_install() { setup_install_base_cli if setup_profiles_enabled; then if setup_is_dry_run; then - setup_run_base_dev_layer setup --dry-run || fatal_error "Python prerequisite profile layer failed." + setup_run_base_dev_layer setup --dry-run || base_std_fatal_error "Python prerequisite profile layer failed." else - setup_run_base_dev_layer setup || fatal_error "Python prerequisite profile layer failed." + setup_run_base_dev_layer setup || base_std_fatal_error "Python prerequisite profile layer failed." fi fi setup_run_project_artifact_setup || return $? setup_seed_user_config if setup_is_dry_run; then - log_info "[DRY-RUN] Base CLI setup check is complete." + base_std_log_info "[DRY-RUN] Base CLI setup check is complete." else - log_info "Base CLI setup is complete." + base_std_log_info "Base CLI setup is complete." fi } diff --git a/cli/bash/commands/basectl/subcommands/setup_profiles.sh b/cli/bash/commands/basectl/subcommands/setup_profiles.sh index 6c55c87d..e544874a 100644 --- a/cli/bash/commands/basectl/subcommands/setup_profiles.sh +++ b/cli/bash/commands/basectl/subcommands/setup_profiles.sh @@ -73,7 +73,7 @@ setup_enable_profile_argument() { return 1 fi - str_split profiles "$compact" "," + base_str_split profiles "$compact" "," for profile in "${profiles[@]}"; do profile="$(setup_normalize_profile_name "$profile")" if ! setup_profile_supported "$profile"; then @@ -118,15 +118,15 @@ setup_run_base_dev_layer() { if setup_is_dry_run && { ! setup_base_python_package_installed "$(setup_pyyaml_package)" || ! setup_base_python_package_installed "$(setup_click_package)"; }; then - log_info "[DRY-RUN] Would run Python prerequisite profile layer after Base Python bootstrap dependencies are installed." + base_std_log_info "[DRY-RUN] Would run Python prerequisite profile layer after Base Python bootstrap dependencies are installed." return 0 fi setup_ensure_cached_paths venv_dir="$_BASE_SETUP_VENV_DIR_CACHE" if ! setup_base_venv_python_bin "$venv_dir" >/dev/null 2>&1; then - log_warn "Python prerequisite profile layer cannot run because Base virtual environment Python was not found at '$venv_dir/bin/python'." - log_warn "$(setup_recovery_venv)" + base_std_log_warn "Python prerequisite profile layer cannot run because Base virtual environment Python was not found at '$venv_dir/bin/python'." + base_std_log_warn "$(setup_recovery_venv)" return 1 fi diff --git a/cli/bash/commands/basectl/subcommands/setup_venv.sh b/cli/bash/commands/basectl/subcommands/setup_venv.sh index 249ba824..a6acaf1d 100644 --- a/cli/bash/commands/basectl/subcommands/setup_venv.sh +++ b/cli/bash/commands/basectl/subcommands/setup_venv.sh @@ -166,17 +166,17 @@ setup_backup_existing_venv_path() { venv_dir="$_BASE_SETUP_VENV_DIR_CACHE" [[ -e "$venv_dir" ]] || return 0 - timestamp="$(setup_backup_timestamp)" || fatal_error "Unable to generate virtual environment backup timestamp." + timestamp="$(setup_backup_timestamp)" || base_std_fatal_error "Unable to generate virtual environment backup timestamp." backup_path="${venv_dir}.backup.${timestamp}" - [[ ! -e "$backup_path" ]] || fatal_error "Virtual environment backup path already exists at '$backup_path'." + [[ ! -e "$backup_path" ]] || base_std_fatal_error "Virtual environment backup path already exists at '$backup_path'." if setup_is_dry_run; then - log_info "[DRY-RUN] Would move $description '$venv_dir' to '$backup_path'." + base_std_log_info "[DRY-RUN] Would move $description '$venv_dir' to '$backup_path'." return 0 fi - log_info "Moving $description '$venv_dir' to '$backup_path'." - mv "$venv_dir" "$backup_path" || fatal_error "Unable to move $description '$venv_dir' to '$backup_path'." + base_std_log_info "Moving $description '$venv_dir' to '$backup_path'." + mv "$venv_dir" "$backup_path" || base_std_fatal_error "Unable to move $description '$venv_dir' to '$backup_path'." } setup_pyyaml_package() { @@ -243,8 +243,8 @@ setup_create_virtualenv() { if setup_virtualenv_exists && ! setup_base_recreate_venv_enabled; then setup_virtualenv_healthy || - fatal_error "$_BASE_SETUP_VENV_HEALTH_MESSAGE $(setup_recovery_venv)" - log_info "Virtual environment already exists at '$venv_dir'." + base_std_fatal_error "$_BASE_SETUP_VENV_HEALTH_MESSAGE $(setup_recovery_venv)" + base_std_log_info "Virtual environment already exists at '$venv_dir'." return 0 fi @@ -255,14 +255,14 @@ setup_create_virtualenv() { fi if setup_is_dry_run; then - log_info "[DRY-RUN] Would create Python virtual environment at '$venv_dir'." + base_std_log_info "[DRY-RUN] Would create Python virtual environment at '$venv_dir'." return 0 fi - python_bin="$(setup_find_platform_python_bin)" || fatal_error "Unable to locate a python3 executable after installation. $(setup_recovery_platform_python)" + python_bin="$(setup_find_platform_python_bin)" || base_std_fatal_error "Unable to locate a python3 executable after installation. $(setup_recovery_platform_python)" - safe_mkdir -p "$(dirname "$venv_dir")" - log_info "Creating Python virtual environment at '$venv_dir'." + base_std_safe_mkdir -p "$(dirname "$venv_dir")" + base_std_log_info "Creating Python virtual environment at '$venv_dir'." "$python_bin" -m venv "$venv_dir" } @@ -271,18 +271,18 @@ setup_upgrade_pip_in_virtualenv() { local python_bin="$2" if setup_is_dry_run; then - log_info "[DRY-RUN] Would upgrade pip in the $description virtual environment." + base_std_log_info "[DRY-RUN] Would upgrade pip in the $description virtual environment." return 0 fi [[ -x "$python_bin" ]] || { - log_error "Cannot upgrade pip because the $description virtual environment Python was not found at '$python_bin'." + base_std_log_error "Cannot upgrade pip because the $description virtual environment Python was not found at '$python_bin'." return 1 } - log_info "Upgrading pip in the $description virtual environment." + base_std_log_info "Upgrading pip in the $description virtual environment." "$python_bin" -m pip install --disable-pip-version-check --upgrade pip || { - log_error "Unable to upgrade pip in the $description virtual environment." + base_std_log_error "Unable to upgrade pip in the $description virtual environment." return 1 } } @@ -336,20 +336,20 @@ setup_install_base_python_package() { venv_dir="$_BASE_SETUP_VENV_DIR_CACHE" if setup_base_python_package_installed "$package"; then - log_info "Python package '$package' is already installed in the Base virtual environment." + base_std_log_info "Python package '$package' is already installed in the Base virtual environment." return 0 fi if setup_is_dry_run; then - log_info "[DRY-RUN] Would install Python package '$package' in the Base virtual environment." + base_std_log_info "[DRY-RUN] Would install Python package '$package' in the Base virtual environment." return 0 fi - python_bin="$(setup_base_venv_python_bin "$venv_dir")" || fatal_error "Base virtual environment Python was not found at '$venv_dir/bin/python'. $(setup_recovery_venv)" + python_bin="$(setup_base_venv_python_bin "$venv_dir")" || base_std_fatal_error "Base virtual environment Python was not found at '$venv_dir/bin/python'. $(setup_recovery_venv)" - log_info "Installing Python package '$package' in the Base virtual environment." + base_std_log_info "Installing Python package '$package' in the Base virtual environment." "$python_bin" -m pip install --disable-pip-version-check "$package" || - fatal_error "Unable to install Python package '$package' in the Base virtual environment." + base_std_fatal_error "Unable to install Python package '$package' in the Base virtual environment." } setup_install_pyyaml() { @@ -484,16 +484,16 @@ setup_run_ci_runtime_install() { setup_install_base_cli if setup_profiles_enabled; then if setup_is_dry_run; then - setup_run_base_dev_layer setup --dry-run || fatal_error "Python prerequisite profile layer failed." + setup_run_base_dev_layer setup --dry-run || base_std_fatal_error "Python prerequisite profile layer failed." else - setup_run_base_dev_layer setup || fatal_error "Python prerequisite profile layer failed." + setup_run_base_dev_layer setup || base_std_fatal_error "Python prerequisite profile layer failed." fi fi setup_run_project_artifact_setup || return $? if setup_is_dry_run; then - log_info "[DRY-RUN] Base CI setup check is complete." + base_std_log_info "[DRY-RUN] Base CI setup check is complete." else - log_info "Base CI setup is complete." + base_std_log_info "Base CI setup is complete." fi } diff --git a/cli/bash/commands/basectl/subcommands/test.sh b/cli/bash/commands/basectl/subcommands/test.sh index c0a6efb0..b72e9469 100644 --- a/cli/bash/commands/basectl/subcommands/test.sh +++ b/cli/bash/commands/basectl/subcommands/test.sh @@ -27,7 +27,7 @@ EOF base_test_usage_error() { base_test_subcommand_usage >&2 - print_error "$*" + base_std_print_error "$*" return 2 } @@ -102,7 +102,7 @@ base_test_subcommand_main() { } wrapper="$BASE_HOME/bin/base-wrapper" - [[ -x "$wrapper" ]] || fatal_error "Base Python wrapper '$wrapper' is missing or is not executable." + [[ -x "$wrapper" ]] || base_std_fatal_error "Base Python wrapper '$wrapper' is missing or is not executable." local command_args=(test-command) if [[ -n "$explicit_project" ]]; then @@ -112,7 +112,7 @@ base_test_subcommand_main() { fi resolve_output="$("$wrapper" --project base base_projects "${command_args[@]}" "${args[@]}" --format command-protocol)" || return $? base_command_protocol_decode_one project-command "$resolve_output" || { - fatal_error "Unable to resolve test command for project '$project'." + base_std_fatal_error "Unable to resolve test command for project '$project'." } resolved_name="${BASE_COMMAND_PROTOCOL_FIELDS[project_name]}" project_root="${BASE_COMMAND_PROTOCOL_FIELDS[project_root]}" @@ -125,7 +125,7 @@ base_test_subcommand_main() { command_runner="${BASE_COMMAND_PROTOCOL_FIELDS[runner]}" [[ -n "$resolved_name" && -n "$project_root" && -n "$manifest_path" && -n "$test_command" ]] || { - fatal_error "Unable to resolve test command for project '$project'." + base_std_fatal_error "Unable to resolve test command for project '$project'." } command_runner="${command_runner:-}" @@ -141,7 +141,7 @@ base_test_subcommand_main() { base_project_activate_environment \ "$resolved_name" "$project_root" "$manifest_path" "$dry_run" "$route_venv_dir" "$uses_uv_manager" >/dev/null - log_info "Running tests for project '$resolved_name': $display_command" + base_std_log_info "Running tests for project '$resolved_name': $display_command" base_validate_command_runner "$command_runner" base_project_run_shell_command "$project_root" "$command_to_run" basectl-test "${extra_args[@]}" } diff --git a/cli/bash/commands/basectl/subcommands/trust.sh b/cli/bash/commands/basectl/subcommands/trust.sh index 4a00e6ce..07d6571b 100644 --- a/cli/bash/commands/basectl/subcommands/trust.sh +++ b/cli/bash/commands/basectl/subcommands/trust.sh @@ -82,7 +82,7 @@ EOF base_trust_usage_error() { base_trust_subcommand_usage >&2 - print_error "$*" + base_std_print_error "$*" return 2 } @@ -130,7 +130,7 @@ base_trust_subcommand_main() { export BASE_CLI_HISTORY_PROJECT="$project_name" fi - [[ -x "$wrapper" ]] || fatal_error "Base Python wrapper '$wrapper' is missing or is not executable." + [[ -x "$wrapper" ]] || base_std_fatal_error "Base Python wrapper '$wrapper' is missing or is not executable." BASE_TRUST_ACTIVE_PROJECT="${BASE_PROJECT:-}" \ BASE_TRUST_ACTIVE_PROJECT_MANIFEST="${BASE_PROJECT_MANIFEST:-}" \ BASE_CLI_DISPLAY_COMMAND="basectl trust" \ diff --git a/cli/bash/commands/basectl/subcommands/update.sh b/cli/bash/commands/basectl/subcommands/update.sh index d8efde31..b5ed66d9 100644 --- a/cli/bash/commands/basectl/subcommands/update.sh +++ b/cli/bash/commands/basectl/subcommands/update.sh @@ -47,7 +47,7 @@ EOF } base_update_usage_error() { - print_error "$*" + base_std_print_error "$*" base_update_subcommand_usage >&2 return 2 } @@ -302,9 +302,9 @@ base_update_report_homebrew_trust_required() { tap="$(base_update_homebrew_tap)" bash_libs_package="$(base_update_homebrew_bash_libs_package)" - log_error "Homebrew requires trust for '$tap' before upgrading Base's tap-owned Bash library dependency." - log_error "Run 'brew trust $tap', then rerun 'basectl update'." - log_error "To trust only the dependency formula instead, run 'brew trust --formula $bash_libs_package'." + base_std_log_error "Homebrew requires trust for '$tap' before upgrading Base's tap-owned Bash library dependency." + base_std_log_error "Run 'brew trust $tap', then rerun 'basectl update'." + base_std_log_error "To trust only the dependency formula instead, run 'brew trust --formula $bash_libs_package'." } base_update_run_homebrew_setup() { @@ -313,7 +313,7 @@ base_update_run_homebrew_setup() { local basectl basectl="$(base_update_homebrew_basectl "$base_home" "$package")" || { - log_error "Unable to locate Homebrew-managed basectl after upgrade." + base_std_log_error "Unable to locate Homebrew-managed basectl after upgrade." return 1 } @@ -347,16 +347,16 @@ base_update_homebrew_install() { local package package="$(base_update_homebrew_package)" - log_info "Detected Homebrew-managed Base install at '$base_home'." + base_std_log_info "Detected Homebrew-managed Base install at '$base_home'." if ((dry_run)); then - log_info "[DRY-RUN] Would run: brew upgrade $package" - log_info "[DRY-RUN] Would run 'basectl setup' if the Homebrew upgrade changes Base's installed version, with inherited Base environment cleared." + base_std_log_info "[DRY-RUN] Would run: brew upgrade $package" + base_std_log_info "[DRY-RUN] Would run 'basectl setup' if the Homebrew upgrade changes Base's installed version, with inherited Base environment cleared." return 0 fi if ! command -v brew >/dev/null 2>&1; then - log_error "Homebrew-managed Base install detected, but 'brew' is not available in PATH." + base_std_log_error "Homebrew-managed Base install detected, but 'brew' is not available in PATH." return 1 fi @@ -366,33 +366,33 @@ base_update_homebrew_install() { fi before_version="$(base_update_homebrew_installed_version "$package")" || { - log_error "Unable to determine installed Homebrew version for $package before upgrade." + base_std_log_error "Unable to determine installed Homebrew version for $package before upgrade." return 1 } - log_info "Running Homebrew upgrade for $package." + base_std_log_info "Running Homebrew upgrade for $package." base_update_run_homebrew_upgrade "$package" exit_code=$? if ((exit_code != 0)); then - log_error "Homebrew upgrade failed. If Homebrew refused to load '$package' or '$(base_update_homebrew_bash_libs_package)' from an untrusted tap, run 'brew trust $(base_update_homebrew_tap)' and retry." + base_std_log_error "Homebrew upgrade failed. If Homebrew refused to load '$package' or '$(base_update_homebrew_bash_libs_package)' from an untrusted tap, run 'brew trust $(base_update_homebrew_tap)' and retry." return "$exit_code" fi after_version="$(base_update_homebrew_installed_version "$package")" || { - log_error "Unable to determine installed Homebrew version for $package after upgrade." + base_std_log_error "Unable to determine installed Homebrew version for $package after upgrade." return 1 } if [[ "$before_version" == "$after_version" ]]; then - log_info "Homebrew Base version is unchanged at '$after_version' after upgrade." - log_info "Skipping basectl setup because the Homebrew Base version did not change." + base_std_log_info "Homebrew Base version is unchanged at '$after_version' after upgrade." + base_std_log_info "Skipping basectl setup because the Homebrew Base version did not change." else - log_info "Homebrew Base version changed from '$before_version' to '$after_version'." - log_info "Running basectl setup after Homebrew upgrade." + base_std_log_info "Homebrew Base version changed from '$before_version' to '$after_version'." + base_std_log_info "Running basectl setup after Homebrew upgrade." base_update_run_homebrew_setup "$base_home" "$package" || return $? fi - log_info "Base update is complete." + base_std_log_info "Base update is complete." } base_update_current_branch() { @@ -461,7 +461,7 @@ base_update_resolve_project() { resolved_manifest="$base_home/base_manifest.yaml" else [[ -x "$wrapper" ]] || { - log_error "Base Python wrapper '$wrapper' is missing or is not executable." + base_std_log_error "Base Python wrapper '$wrapper' is missing or is not executable." return 1 } @@ -471,7 +471,7 @@ base_update_resolve_project() { resolved_root="${BASE_COMMAND_PROTOCOL_FIELDS[project_root]}" resolved_manifest="${BASE_COMMAND_PROTOCOL_FIELDS[manifest_path]}" [[ "$resolved_name" == "$project" && -n "$resolved_root" && -n "$resolved_manifest" ]] || { - log_error "Unable to resolve Base project '$project'." + base_std_log_error "Unable to resolve Base project '$project'." return 1 } fi @@ -529,64 +529,64 @@ base_update_subcommand_main() { base_update_resolve_project "$base_home" "$project" resolved_project repo manifest_path || return $? [[ -n "$resolved_project" && -n "$repo" && -n "$manifest_path" ]] || { - log_error "Unable to resolve Base project '$project'." + base_std_log_error "Unable to resolve Base project '$project'." return 1 } - log_debug "Running 'basectl update' for project '$resolved_project'." + base_std_log_debug "Running 'basectl update' for project '$resolved_project'." branch="$(base_update_current_branch "$repo")" || { if [[ "$resolved_project" == base ]] && base_update_is_homebrew_install "$base_home"; then base_update_homebrew_install "$base_home" "$dry_run" return $? fi - log_error "Project '$resolved_project' repository '$repo' is not a Git repository." + base_std_log_error "Project '$resolved_project' repository '$repo' is not a Git repository." return 1 } update_branch="$(base_update_default_branch "$repo")" || { - log_error "Unable to determine the default branch for project '$resolved_project'." + base_std_log_error "Unable to determine the default branch for project '$resolved_project'." return 1 } if [[ "$branch" != "$update_branch" ]]; then - log_error "Project '$resolved_project' update only runs on default branch '$update_branch'; current branch is '$branch'." + base_std_log_error "Project '$resolved_project' update only runs on default branch '$update_branch'; current branch is '$branch'." return 1 fi if ! base_update_worktree_clean "$repo"; then - log_error "Project '$resolved_project' repository has tracked local changes. Commit, stash, or remove them before running basectl update." + base_std_log_error "Project '$resolved_project' repository has tracked local changes. Commit, stash, or remove them before running basectl update." return 1 fi if base_update_has_untracked_files "$repo"; then - log_warn "Project '$resolved_project' repository has untracked files. Continuing because tracked files are clean." + base_std_log_warn "Project '$resolved_project' repository has untracked files. Continuing because tracked files are clean." fi if ((dry_run)); then - log_info "[DRY-RUN] Would update project '$resolved_project' repository at '$repo'." - log_info "[DRY-RUN] Would run 'basectl setup $resolved_project' if the Git update changes the repository." + base_std_log_info "[DRY-RUN] Would update project '$resolved_project' repository at '$repo'." + base_std_log_info "[DRY-RUN] Would run 'basectl setup $resolved_project' if the Git update changes the repository." return 0 fi base_update_source_git_library || return 1 before_revision="$(base_update_head_revision "$repo")" || { - log_error "Unable to read current revision for project '$resolved_project'." + base_std_log_error "Unable to read current revision for project '$resolved_project'." return 1 } - log_info "Updating project '$resolved_project' repository at '$repo'." - git_update_repo "$repo" "" "$update_branch" || return 1 + base_std_log_info "Updating project '$resolved_project' repository at '$repo'." + base_git_update_repo "$repo" "" "$update_branch" || return 1 after_revision="$(base_update_head_revision "$repo")" || { - log_error "Unable to read updated revision for project '$resolved_project'." + base_std_log_error "Unable to read updated revision for project '$resolved_project'." return 1 } if [[ "$before_revision" == "$after_revision" ]]; then - log_info "Project '$resolved_project' repository is already up to date on '$update_branch' at '$after_revision'." - log_info "Skipping basectl setup $resolved_project because the repository did not change." + base_std_log_info "Project '$resolved_project' repository is already up to date on '$update_branch' at '$after_revision'." + base_std_log_info "Skipping basectl setup $resolved_project because the repository did not change." else - log_info "Project '$resolved_project' repository updated from '$before_revision' to '$after_revision' on '$update_branch'." - log_info "Running basectl setup $resolved_project after update." + base_std_log_info "Project '$resolved_project' repository updated from '$before_revision' to '$after_revision' on '$update_branch'." + base_std_log_info "Running basectl setup $resolved_project after update." base_update_run_setup "$base_home" "$resolved_project" || return $? fi - log_info "Project '$resolved_project' update is complete." + base_std_log_info "Project '$resolved_project' update is complete." } diff --git a/cli/bash/commands/basectl/subcommands/update_profile.sh b/cli/bash/commands/basectl/subcommands/update_profile.sh index fa84089e..655331a1 100644 --- a/cli/bash/commands/basectl/subcommands/update_profile.sh +++ b/cli/bash/commands/basectl/subcommands/update_profile.sh @@ -35,14 +35,14 @@ EOF } base_update_profile_usage_error() { - print_error "$*" + base_std_print_error "$*" printf "Run 'basectl update-profile --help' for usage.\n" >&2 return 2 } base_update_profile_source_file_library() { import_base_lib file/lib_file.sh - assert_function_exists file_section_exists file_section_needs_update + base_std_assert_function_exists base_file_section_exists base_file_section_needs_update } base_update_profile_shell_double_quote() { @@ -152,15 +152,15 @@ base_update_profile_backup_existing_file() { [[ -f "$target_file" ]] || return 0 backup_path="$(base_update_profile_backup_path "$target_file" "$timestamp")" || - fatal_error "Unable to resolve backup path for '$target_file'." + base_std_fatal_error "Unable to resolve backup path for '$target_file'." if ((dry_run)); then - log_info "[DRY-RUN] Would back up '$target_file' to '$backup_path'." + base_std_log_info "[DRY-RUN] Would back up '$target_file' to '$backup_path'." return 0 fi - log_info "Backing up '$target_file' to '$backup_path'." - cp -p "$target_file" "$backup_path" || fatal_error "Unable to back up '$target_file' to '$backup_path'." + base_std_log_info "Backing up '$target_file' to '$backup_path'." + cp -p "$target_file" "$backup_path" || base_std_fatal_error "Unable to back up '$target_file' to '$backup_path'." } base_update_profile_update_file_needs_change() { @@ -173,7 +173,7 @@ base_update_profile_update_file_needs_change() { [[ -f "$target_file" ]] || return 0 mapfile -t lines < <(base_update_profile_section_lines "$snippet_name") || return 2 - file_section_needs_update "$target_file" "$start_marker" "$end_marker" "${lines[@]}" + base_file_section_needs_update "$target_file" "$start_marker" "$end_marker" "${lines[@]}" } base_update_profile_remove_file_needs_change() { @@ -181,7 +181,7 @@ base_update_profile_remove_file_needs_change() { local start_marker="$2" local end_marker="$3" - file_section_exists "$target_file" "$start_marker" "$end_marker" + base_file_section_exists "$target_file" "$start_marker" "$end_marker" } base_update_profile_update_file() { @@ -211,14 +211,14 @@ base_update_profile_update_file() { if ((dry_run)); then base_update_profile_backup_existing_file "$target_file" "$backup_timestamp" "$dry_run" || return 1 - log_info "[DRY-RUN] Would update '$target_file' with section '$snippet_name'." + base_std_log_info "[DRY-RUN] Would update '$target_file' with section '$snippet_name'." return 0 fi base_update_profile_backup_existing_file "$target_file" "$backup_timestamp" "$dry_run" || return 1 - safe_touch "$target_file" + base_std_safe_touch "$target_file" base_update_profile_prepare_section_spacing "$target_file" "$start_marker" || return 1 - update_file_section "$target_file" "$start_marker" "$end_marker" "${lines[@]}" + base_file_update_file_section "$target_file" "$start_marker" "$end_marker" "${lines[@]}" } base_update_profile_remove_file() { @@ -246,12 +246,12 @@ base_update_profile_remove_file() { if ((dry_run)); then base_update_profile_backup_existing_file "$target_file" "$backup_timestamp" "$dry_run" || return 1 - log_info "[DRY-RUN] Would remove section '$snippet_name' from '$target_file'." + base_std_log_info "[DRY-RUN] Would remove section '$snippet_name' from '$target_file'." return 0 fi base_update_profile_backup_existing_file "$target_file" "$backup_timestamp" "$dry_run" || return 1 - update_file_section -r "$target_file" "$start_marker" "$end_marker" + base_file_update_file_section -r "$target_file" "$start_marker" "$end_marker" } base_update_profile_state_dir() { @@ -294,12 +294,12 @@ base_update_profile_write_profile_conf() { fi if ((dry_run)); then - log_info "[DRY-RUN] Would update '$profile_conf'." + base_std_log_info "[DRY-RUN] Would update '$profile_conf'." return 0 fi - safe_mkdir -p "$state_dir" - temp_file="$(mktemp "$profile_conf.XXXXXX")" || fatal_error "Unable to create temporary profile config for '$profile_conf'." + base_std_safe_mkdir -p "$state_dir" + temp_file="$(mktemp "$profile_conf.XXXXXX")" || base_std_fatal_error "Unable to create temporary profile config for '$profile_conf'." if ! { printf '%s\n' '# Managed by Base. Run `basectl update-profile` to refresh this file.' @@ -308,10 +308,10 @@ base_update_profile_write_profile_conf() { printf 'BASE_ENABLE_ZSH_DEFAULTS=%s\n' "$enable_value" } > "$temp_file"; then rm -f -- "$temp_file" - fatal_error "Unable to write Base profile config '$profile_conf'." + base_std_fatal_error "Unable to write Base profile config '$profile_conf'." fi - mv -f -- "$temp_file" "$profile_conf" || fatal_error "Unable to update Base profile config '$profile_conf'." + mv -f -- "$temp_file" "$profile_conf" || base_std_fatal_error "Unable to update Base profile config '$profile_conf'." } base_update_profile_subcommand_main() { @@ -360,14 +360,14 @@ base_update_profile_subcommand_main() { return $? fi - log_debug "Running 'basectl update-profile'." + base_std_log_debug "Running 'basectl update-profile'." base_home="$(basectl_runtime_base_home)" || { - print_error "${BASE_CLI_ERROR_MESSAGE:-Unable to find Base home.}" + base_std_print_error "${BASE_CLI_ERROR_MESSAGE:-Unable to find Base home.}" return 1 } if [[ "${BASE_HOME:-}" != "$base_home" ]]; then - print_error "Resolved Base home '$base_home' does not match runtime BASE_HOME '${BASE_HOME:-unset}'." + base_std_print_error "Resolved Base home '$base_home' does not match runtime BASE_HOME '${BASE_HOME:-unset}'." printf " This command must be invoked through the Base dispatcher, not directly.\n" >&2 printf " Fix: unset BASE_HOME and run 'basectl update-profile' through the installed 'basectl' binary.\n" >&2 return 1 @@ -375,7 +375,7 @@ base_update_profile_subcommand_main() { export BASE_HOME base_update_profile_source_file_library || return 1 - backup_timestamp="$(setup_backup_timestamp)" || fatal_error "Unable to generate update-profile backup timestamp." + backup_timestamp="$(setup_backup_timestamp)" || base_std_fatal_error "Unable to generate update-profile backup timestamp." if ((remove_sections)); then base_update_profile_remove_file "$HOME/.bash_profile" bash_profile "$dry_run" "$backup_timestamp" || return 1 diff --git a/cli/bash/commands/basectl/subcommands/workspace.sh b/cli/bash/commands/basectl/subcommands/workspace.sh index 1a8e0643..de9bfc41 100644 --- a/cli/bash/commands/basectl/subcommands/workspace.sh +++ b/cli/bash/commands/basectl/subcommands/workspace.sh @@ -199,7 +199,7 @@ EOF base_workspace_usage_error() { base_workspace_subcommand_usage >&2 - print_error "$*" + base_std_print_error "$*" return 2 } @@ -239,6 +239,6 @@ base_workspace_subcommand_main() { esac done - [[ -x "$wrapper" ]] || fatal_error "Base Python wrapper '$wrapper' is missing or is not executable." + [[ -x "$wrapper" ]] || base_std_fatal_error "Base Python wrapper '$wrapper' is missing or is not executable." "$wrapper" --project base base_projects "$workspace_command" "${args[@]}" } diff --git a/cli/bash/commands/basectl/tests/activate.bats b/cli/bash/commands/basectl/tests/activate.bats index 7eaf8233..15103d58 100644 --- a/cli/bash/commands/basectl/tests/activate.bats +++ b/cli/bash/commands/basectl/tests/activate.bats @@ -17,7 +17,7 @@ setup_activate_lifecycle_fixture() { BASE_CLI_RUNTIME_OWNER \ BASE_CLI_RUN_ID \ BASE_CLI_RUN_ROOT \ - BASE_CLI_PRIMARY_LOG \ + BASE_BASH_LIBS_PRIMARY_LOG \ BASE_CLI_HISTORY_PARENT_RUN_ID \ BASE_CLI_HISTORY_STARTED_AT \ BASE_CLI_HISTORY_SCOPE \ diff --git a/cli/bash/commands/basectl/tests/check.bats b/cli/bash/commands/basectl/tests/check.bats index 78248ed0..07876639 100644 --- a/cli/bash/commands/basectl/tests/check.bats +++ b/cli/bash/commands/basectl/tests/check.bats @@ -248,7 +248,7 @@ EOF create_base_venv_stub "$venv_dir" run_base_command \ - DRY_RUN=true \ + BASE_BASH_LIBS_DRY_RUN=true \ BASE_SETUP_RECREATE_VENV=true \ check diff --git a/cli/bash/commands/basectl/tests/export-context.bats b/cli/bash/commands/basectl/tests/export-context.bats index 91ab86f1..006d92ca 100644 --- a/cli/bash/commands/basectl/tests/export-context.bats +++ b/cli/bash/commands/basectl/tests/export-context.bats @@ -24,7 +24,7 @@ load ./basectl_helpers.bash bash -c ' source "$BASE_HOME/base_init.sh" source "$BASE_HOME/cli/bash/commands/basectl/subcommands/export_context.sh" - arg_parse() { + base_arg_parse() { printf "%s\n" "$*" > "${BASE_TEST_ARG_PARSE_STATE:?}" return 2 } diff --git a/cli/bash/commands/basectl/tests/gh-branch-worktree.bats b/cli/bash/commands/basectl/tests/gh-branch-worktree.bats index d813c04f..06db82d5 100644 --- a/cli/bash/commands/basectl/tests/gh-branch-worktree.bats +++ b/cli/bash/commands/basectl/tests/gh-branch-worktree.bats @@ -9,19 +9,19 @@ load ./basectl_helpers.bash bash -c ' source "$BASE_HOME/base_init.sh" source "$BASE_HOME/cli/bash/commands/basectl/subcommands/gh.sh" - git_worktree_path_for_branch() { + base_git_worktree_path_for_branch() { printf "%s\n" "/tmp/shared-worktree" } - git_branch_upstream() { + base_git_branch_upstream() { printf "%s\n" "origin/feature" } - git_branch_merged_to_ref() { + base_git_branch_merged_to_ref() { [[ "$2" == "feature" && "$3" == "main" ]] } - git_list_remote_branches() { + base_git_list_remote_branches() { printf "%s\n" "main" "feature" } - git_list_worktree_branches() { + base_git_list_worktree_branches() { printf "%s\t%s\n" "/tmp/shared-worktree" "feature" } remote_branches="$(base_gh_list_remote_branches)" diff --git a/cli/bash/commands/basectl/tests/gh.bats b/cli/bash/commands/basectl/tests/gh.bats index c9161ea2..4e7f1dad 100644 --- a/cli/bash/commands/basectl/tests/gh.bats +++ b/cli/bash/commands/basectl/tests/gh.bats @@ -276,13 +276,13 @@ run_gh_subcommand() { bash -c ' source "$BASE_HOME/base_init.sh" source "$BASE_HOME/cli/bash/commands/basectl/subcommands/gh.sh" - [[ "$(type -t gh_require_cli)" == "function" ]] - [[ "$(type -t gh_auth_status_diagnostics)" == "function" ]] - [[ "$(type -t gh_run)" == "function" ]] - [[ "$(type -t git_detect_default_branch)" == "function" ]] - [[ "$(type -t gh_infer_repo_from_origin)" == "function" ]] - [[ "$(type -t git_worktree_path_for_branch)" == "function" ]] - [[ "$(type -t git_branch_merged_to_ref)" == "function" ]] + [[ "$(type -t base_gh_require_cli)" == "function" ]] + [[ "$(type -t base_gh_auth_status_diagnostics)" == "function" ]] + [[ "$(type -t base_gh_run)" == "function" ]] + [[ "$(type -t base_git_detect_default_branch)" == "function" ]] + [[ "$(type -t base_gh_infer_repo_from_origin)" == "function" ]] + [[ "$(type -t base_git_worktree_path_for_branch)" == "function" ]] + [[ "$(type -t base_git_branch_merged_to_ref)" == "function" ]] ' [ "$status" -eq 0 ] @@ -388,10 +388,10 @@ run_gh_subcommand() { bash -c ' source "$BASE_HOME/base_init.sh" source "$BASE_HOME/cli/bash/commands/basectl/subcommands/gh.sh" - git_detect_default_branch() { + base_git_detect_default_branch() { printf -v "$2" "%s" "develop" } - gh_infer_repo_from_origin() { + base_gh_infer_repo_from_origin() { printf -v "$2" "%s" "owner/repo" } printf "default=%s\n" "$(base_gh_default_branch)" @@ -411,7 +411,7 @@ run_gh_subcommand() { bash -c ' source "$BASE_HOME/base_init.sh" source "$BASE_HOME/cli/bash/commands/basectl/subcommands/gh.sh" - str_join() { + base_str_join() { printf "%s\n" "$*" > "${BASE_GH_TEST_STATE_DIR:?}/str-join" printf -v "$1" "%s" "joined-by-helper" } @@ -1536,8 +1536,8 @@ EOF cd "$1" source "$BASE_HOME/base_init.sh" source "$BASE_HOME/cli/bash/commands/basectl/subcommands/gh.sh" - eval "$(declare -f std_make_temp_file | sed "1s/std_make_temp_file/__orig_std_make_temp_file/")" - std_make_temp_file() { + eval "$(declare -f base_std_make_temp_file | sed "1s/base_std_make_temp_file/__orig_std_make_temp_file/")" + base_std_make_temp_file() { printf "%s\n" "$*" >> "${BASE_GH_TEST_STATE_DIR:?}/temp-helper" __orig_std_make_temp_file "$@" } diff --git a/cli/bash/commands/basectl/tests/project-command-helpers.bats b/cli/bash/commands/basectl/tests/project-command-helpers.bats index 24748780..3034f33f 100644 --- a/cli/bash/commands/basectl/tests/project-command-helpers.bats +++ b/cli/bash/commands/basectl/tests/project-command-helpers.bats @@ -137,7 +137,7 @@ source_project_command_helpers() { bash -c ' source "$BASE_REPO_ROOT/cli/bash/commands/basectl/subcommands/project_command_helpers.sh" HOME="$1" - log_warn() { printf "WARN:%s\n" "$*"; } + base_std_log_warn() { printf "WARN:%s\n" "$*"; } base_project_activate_environment demo "$2" "$3" 0 "$4" false ' bash "$TEST_HOME" "$project_root" "$manifest_path" "$venv_dir" @@ -150,7 +150,7 @@ source_project_command_helpers() { bash -c ' source "$BASE_REPO_ROOT/cli/bash/commands/basectl/subcommands/project_command_helpers.sh" HOME="$1" - log_warn() { printf "WARN:%s\n" "$*"; } + base_std_log_warn() { printf "WARN:%s\n" "$*"; } base_project_activate_environment demo "$2" "$3" 1 "$4" false ' bash "$TEST_HOME" "$project_root" "$manifest_path" "$venv_dir" diff --git a/cli/bash/commands/basectl/tests/repo.bats b/cli/bash/commands/basectl/tests/repo.bats index 2bb52bbb..06543867 100644 --- a/cli/bash/commands/basectl/tests/repo.bats +++ b/cli/bash/commands/basectl/tests/repo.bats @@ -140,12 +140,12 @@ run_repo_command_with_mocks() { bash -c ' source "$BASE_HOME/base_init.sh" source "$BASE_HOME/cli/bash/commands/basectl/subcommands/repo.sh" - [[ "$(type -t gh_require_cli)" == "function" ]] - [[ "$(type -t gh_auth_status_diagnostics)" == "function" ]] - [[ "$(type -t gh_run)" == "function" ]] - [[ "$(type -t gh_infer_repo_from_origin)" == "function" ]] - [[ "$(type -t git_detect_default_branch)" == "function" ]] - [[ "$(type -t gh_repo_default_branch)" == "function" ]] + [[ "$(type -t base_gh_require_cli)" == "function" ]] + [[ "$(type -t base_gh_auth_status_diagnostics)" == "function" ]] + [[ "$(type -t base_gh_run)" == "function" ]] + [[ "$(type -t base_gh_infer_repo_from_origin)" == "function" ]] + [[ "$(type -t base_git_detect_default_branch)" == "function" ]] + [[ "$(type -t base_gh_repo_default_branch)" == "function" ]] ' [ "$status" -eq 0 ] @@ -161,13 +161,13 @@ run_repo_command_with_mocks() { base_repo_require_gh() { return 0 } - gh_infer_repo_from_origin() { + base_gh_infer_repo_from_origin() { printf -v "$2" "%s" "owner/repo" } - git_detect_default_branch() { + base_git_detect_default_branch() { printf -v "$2" "%s" "develop" } - gh_repo_default_branch() { + base_gh_repo_default_branch() { printf -v "$2" "%s" "trunk" } printf "repo=%s\n" "$(base_repo_infer_github_repo /tmp/repo)" diff --git a/cli/bash/commands/basectl/tests/runtime-dispatch.bats b/cli/bash/commands/basectl/tests/runtime-dispatch.bats index cf600ece..2175a053 100644 --- a/cli/bash/commands/basectl/tests/runtime-dispatch.bats +++ b/cli/bash/commands/basectl/tests/runtime-dispatch.bats @@ -55,7 +55,7 @@ load ./basectl_helpers.bash BASE_CACHE_DIR="$cache_root" \ bash -c ' source "$BASE_HOME/cli/bash/commands/basectl/basectl.sh" - log_debug() { :; } + base_std_log_debug() { :; } basectl_do_setup() { return 7; } basectl_history_record() { :; } basectl_main setup @@ -79,7 +79,7 @@ load ./basectl_helpers.bash BASE_CACHE_DIR="$cache_root" \ bash -c ' source "$BASE_HOME/cli/bash/commands/basectl/basectl.sh" - log_debug() { :; } + base_std_log_debug() { :; } basectl_do_setup() { mkdir -p "$BASE_CLI_RUN_ROOT/tmp/base_setup" printf "temporary\\n" >"$BASE_CLI_RUN_ROOT/tmp/base_setup/file.txt" @@ -108,7 +108,7 @@ load ./basectl_helpers.bash BASE_CACHE_DIR="$cache_root" \ bash -c ' source "$BASE_HOME/cli/bash/commands/basectl/basectl.sh" - log_debug() { :; } + base_std_log_debug() { :; } basectl_do_setup() { mkdir -p "$BASE_CLI_RUN_ROOT/tmp/base_setup" printf "temporary\\n" >"$BASE_CLI_RUN_ROOT/tmp/base_setup/file.txt" @@ -190,7 +190,7 @@ load ./basectl_helpers.bash BASE_HOME="$BASE_REPO_ROOT" \ bash -c ' source "$BASE_HOME/cli/bash/commands/basectl/basectl.sh" - log_debug() { :; } + base_std_log_debug() { :; } basectl_get_base_home() { return 0; } basectl_do_version() { printf "keep=%s\n" "${BASE_CLI_KEEP_TEMP:-}"; } basectl_main --keep-temp version @@ -229,7 +229,7 @@ EOF BASE_TEST_FAKE_BASE_HOME="$fake_base_home" \ bash -c ' source "$BASE_HOME/cli/bash/commands/basectl/basectl.sh" - log_debug() { :; } + base_std_log_debug() { :; } basectl_should_start_shell() { return 0; } basectl_get_base_home() { BASE_HOME="$BASE_TEST_FAKE_BASE_HOME"; export BASE_HOME; } basectl_do_activate() { printf "activate=%s preserve=%s\n" "$*" "${BASE_ACTIVATE_PRESERVE_CWD:-}"; } @@ -256,7 +256,7 @@ EOF BASE_TEST_FAKE_BASE_HOME="$fake_base_home" \ bash -c ' source "$BASE_HOME/cli/bash/commands/basectl/basectl.sh" - log_debug() { :; } + base_std_log_debug() { :; } basectl_should_start_shell() { return 0; } basectl_get_base_home() { BASE_HOME="$BASE_TEST_FAKE_BASE_HOME"; export BASE_HOME; } basectl_do_activate() { printf "activate=%s preserve=%s\n" "$*" "${BASE_ACTIVATE_PRESERVE_CWD:-}"; } @@ -489,8 +489,8 @@ EOF cat > "$script_path" <<'EOF' main() { - printf 'LOG_DEBUG=%s\n' "${LOG_DEBUG:-unset}" - printf 'LOG_UTC=%s\n' "${LOG_UTC:-unset}" + printf 'BASE_BASH_LIBS_LOG_DEBUG=%s\n' "${BASE_BASH_LIBS_LOG_DEBUG:-unset}" + printf 'BASE_BASH_LIBS_LOG_UTC=%s\n' "${BASE_BASH_LIBS_LOG_UTC:-unset}" printf 'BASE_CLI_COLOR=%s\n' "${BASE_CLI_COLOR:-unset}" printf 'args=%s\n' "$*" } @@ -502,8 +502,8 @@ EOF "$BASE_REPO_ROOT/bin/basectl" "$script_path" --debug-wrapper --utc-wrapper --color [ "$status" -eq 0 ] - [[ "$output" == *"LOG_DEBUG=1"* ]] - [[ "$output" == *"LOG_UTC=1"* ]] + [[ "$output" == *"BASE_BASH_LIBS_LOG_DEBUG=1"* ]] + [[ "$output" == *"BASE_BASH_LIBS_LOG_UTC=1"* ]] [[ "$output" == *"BASE_CLI_COLOR=1"* ]] grep -Fqx 'args=' <<<"$output" } diff --git a/cli/bash/commands/basectl/tests/runtime-shell.bats b/cli/bash/commands/basectl/tests/runtime-shell.bats index 21987fde..6c8e3531 100644 --- a/cli/bash/commands/basectl/tests/runtime-shell.bats +++ b/cli/bash/commands/basectl/tests/runtime-shell.bats @@ -193,7 +193,7 @@ EOF #!/usr/bin/env bash if [[ "${1:-}" == "-m" && "${2:-}" == "base_projects" && "${3:-}" == "activation-sources" && "${4:-}" == "demo" ]]; then printf 'startup-run-root=%s\n' "${BASE_CLI_RUN_ROOT:-unset}" >&2 - printf 'startup-primary-log=%s\n' "${BASE_CLI_PRIMARY_LOG:-unset}" >&2 + printf 'startup-primary-log=%s\n' "${BASE_BASH_LIBS_PRIMARY_LOG:-unset}" >&2 printf 'startup-history-scope=%s\n' "${BASE_CLI_HISTORY_SCOPE:-unset}" >&2 base_test_protocol_begin activation-source 0 base_test_protocol_end @@ -226,7 +226,7 @@ EOF BASE_CLI_RUNTIME_OWNER=base \ BASE_CLI_RUN_ID=activation-run-id \ BASE_CLI_RUN_ROOT="$activation_run_root" \ - BASE_CLI_PRIMARY_LOG="$activation_log" \ + BASE_BASH_LIBS_PRIMARY_LOG="$activation_log" \ BASE_CLI_KEEP_TEMP=true \ BASE_CLI_HISTORY_PARENT_RUN_ID=activation-run-id \ BASE_CLI_HISTORY_STARTED_AT=2026-07-20T00:00:00Z \ @@ -243,7 +243,7 @@ EOF BASE_CLI_RUNTIME_OWNER \ BASE_CLI_RUN_ID \ BASE_CLI_RUN_ROOT \ - BASE_CLI_PRIMARY_LOG \ + BASE_BASH_LIBS_PRIMARY_LOG \ BASE_CLI_HISTORY_PARENT_RUN_ID \ BASE_CLI_HISTORY_STARTED_AT \ BASE_CLI_HISTORY_SCOPE \ @@ -277,7 +277,7 @@ EOF BASE_CLI_RUNTIME_OWNER \ BASE_CLI_RUN_ID \ BASE_CLI_RUN_ROOT \ - BASE_CLI_PRIMARY_LOG \ + BASE_BASH_LIBS_PRIMARY_LOG \ BASE_CLI_HISTORY_PARENT_RUN_ID \ BASE_CLI_HISTORY_STARTED_AT \ BASE_CLI_HISTORY_SCOPE \ @@ -347,7 +347,7 @@ EOF BASE_CLI_RUNTIME_OWNER=base \ BASE_CLI_RUN_ID=failed-activation-run-id \ BASE_CLI_RUN_ROOT="$activation_run_root" \ - BASE_CLI_PRIMARY_LOG="$activation_log" \ + BASE_BASH_LIBS_PRIMARY_LOG="$activation_log" \ BASE_CLI_HISTORY_PARENT_RUN_ID=failed-activation-run-id \ BASE_CLI_HISTORY_STARTED_AT=2026-07-20T00:00:00Z \ BASE_CLI_HISTORY_SCOPE=internal \ diff --git a/cli/bash/commands/basectl/tests/setup.bats b/cli/bash/commands/basectl/tests/setup.bats index 4958648d..c1ce3a7f 100644 --- a/cli/bash/commands/basectl/tests/setup.bats +++ b/cli/bash/commands/basectl/tests/setup.bats @@ -1403,7 +1403,7 @@ EOF [[ "$output" == *"[DRY-RUN] Would run Python prerequisite profile layer after Base Python bootstrap dependencies are installed."* ]] } -@test "basectl setup ignores inherited DRY_RUN without --dry-run" { +@test "basectl setup ignores inherited BASE_BASH_LIBS_DRY_RUN without --dry-run" { local installer local venv_dir="$TEST_HOME/.base.d/base/.venv" @@ -1411,7 +1411,7 @@ EOF installer="$(create_homebrew_installer_stub)" run_base_command \ - DRY_RUN=true \ + BASE_BASH_LIBS_DRY_RUN=true \ BASE_SETUP_ALLOW_NONINTERACTIVE_XCODE_INSTALL=true \ BASE_SETUP_HOMEBREW_INSTALLER_SCRIPT="$installer" \ setup diff --git a/cli/bash/commands/basectl/tests/update-profile.bats b/cli/bash/commands/basectl/tests/update-profile.bats index eed8dd32..76d80b8f 100644 --- a/cli/bash/commands/basectl/tests/update-profile.bats +++ b/cli/bash/commands/basectl/tests/update-profile.bats @@ -37,10 +37,10 @@ create_minimal_bash_libs_fixture() { mkdir -p "$bash_libs_dir/std" cat > "$bash_libs_dir/std/lib_std.sh" <<'EOF' #!/usr/bin/env bash -add_to_path() { return 0; } -log_debug() { return 0; } -print_error() { printf 'ERROR: %s\n' "$*" >&2; } -fatal_error() { printf 'ERROR: %s\n' "$*" >&2; return 1; } +base_std_add_to_path() { return 0; } +base_std_log_debug() { return 0; } +base_std_print_error() { printf 'ERROR: %s\n' "$*" >&2; } +base_std_fatal_error() { printf 'ERROR: %s\n' "$*" >&2; return 1; } EOF } @@ -211,7 +211,7 @@ EOF source "$BASE_HOME/base_init.sh" source "$BASE_HOME/cli/bash/commands/basectl/subcommands/update_profile.sh" base_update_profile_source_file_library - file_section_needs_update() { + base_file_section_needs_update() { printf "helper_target=%s\n" "$1" printf "helper_start=%s\n" "$2" printf "helper_end=%s\n" "$3" @@ -245,7 +245,7 @@ EOF source "$BASE_HOME/base_init.sh" source "$BASE_HOME/cli/bash/commands/basectl/subcommands/update_profile.sh" base_update_profile_source_file_library - file_section_exists() { + base_file_section_exists() { printf "helper_target=%s\n" "$1" printf "helper_start=%s\n" "$2" printf "helper_end=%s\n" "$3" diff --git a/cli/bash/commands/basectl/tests/update.bats b/cli/bash/commands/basectl/tests/update.bats index ef6cc3a7..4a65e838 100644 --- a/cli/bash/commands/basectl/tests/update.bats +++ b/cli/bash/commands/basectl/tests/update.bats @@ -131,11 +131,11 @@ assert_status() { BASE_HOME="$fake_base" \ BASE_REPO_ROOT="$BASE_REPO_ROOT" \ bash -c ' - log_debug() { :; } - log_error() { printf "ERROR: %s\n" "$*"; } - log_info() { printf "INFO: %s\n" "$*"; } - log_warn() { printf "WARN: %s\n" "$*"; } - print_error() { printf "ERROR: %s\n" "$*"; } + base_std_log_debug() { :; } + base_std_log_error() { printf "ERROR: %s\n" "$*"; } + base_std_log_info() { printf "INFO: %s\n" "$*"; } + base_std_log_warn() { printf "WARN: %s\n" "$*"; } + base_std_print_error() { printf "ERROR: %s\n" "$*"; } source "$BASE_REPO_ROOT/cli/bash/commands/basectl/subcommands/update.sh" base_update_run_homebrew_upgrade() { printf "brew should not run\n"; return 99; } base_update_run_homebrew_setup() { printf "setup should not run\n"; return 99; } @@ -183,11 +183,11 @@ EOF BASE_REPO_ROOT="$BASE_REPO_ROOT" \ PATH="$fake_bin:/usr/bin:/bin:/usr/sbin:/sbin" \ bash -c ' - log_debug() { :; } - log_error() { printf "ERROR: %s\n" "$*"; } - log_info() { printf "INFO: %s\n" "$*"; } - log_warn() { printf "WARN: %s\n" "$*"; } - print_error() { printf "ERROR: %s\n" "$*"; } + base_std_log_debug() { :; } + base_std_log_error() { printf "ERROR: %s\n" "$*"; } + base_std_log_info() { printf "INFO: %s\n" "$*"; } + base_std_log_warn() { printf "WARN: %s\n" "$*"; } + base_std_print_error() { printf "ERROR: %s\n" "$*"; } source "$BASE_REPO_ROOT/cli/bash/commands/basectl/subcommands/update.sh" base_update_subcommand_main ' @@ -258,11 +258,11 @@ EOF BASE_HOME="$BASE_REPO_ROOT" \ PATH="$fake_bin:/usr/bin:/bin:/usr/sbin:/sbin" \ bash -c ' - log_debug() { :; } - log_error() { printf "ERROR: %s\n" "$*"; } - log_info() { printf "INFO: %s\n" "$*"; } - log_warn() { printf "WARN: %s\n" "$*"; } - print_error() { printf "ERROR: %s\n" "$*"; } + base_std_log_debug() { :; } + base_std_log_error() { printf "ERROR: %s\n" "$*"; } + base_std_log_info() { printf "INFO: %s\n" "$*"; } + base_std_log_warn() { printf "WARN: %s\n" "$*"; } + base_std_print_error() { printf "ERROR: %s\n" "$*"; } source "$BASE_HOME/base_init.sh" source "$BASE_HOME/cli/bash/commands/basectl/subcommands/update.sh" base_update_homebrew_prefix base @@ -316,11 +316,11 @@ EOF BASE_REPO_ROOT="$BASE_REPO_ROOT" \ PATH="$fake_bin:/usr/bin:/bin:/usr/sbin:/sbin" \ bash -c ' - log_debug() { :; } - log_error() { printf "ERROR: %s\n" "$*"; } - log_info() { printf "INFO: %s\n" "$*"; } - log_warn() { printf "WARN: %s\n" "$*"; } - print_error() { printf "ERROR: %s\n" "$*"; } + base_std_log_debug() { :; } + base_std_log_error() { printf "ERROR: %s\n" "$*"; } + base_std_log_info() { printf "INFO: %s\n" "$*"; } + base_std_log_warn() { printf "WARN: %s\n" "$*"; } + base_std_print_error() { printf "ERROR: %s\n" "$*"; } source "$BASE_REPO_ROOT/cli/bash/commands/basectl/subcommands/update.sh" base_update_subcommand_main ' @@ -366,11 +366,11 @@ EOF BASE_REPO_ROOT="$BASE_REPO_ROOT" \ PATH="$fake_bin:/usr/bin:/bin:/usr/sbin:/sbin" \ bash -c ' - log_debug() { :; } - log_error() { printf "ERROR: %s\n" "$*"; } - log_info() { printf "INFO: %s\n" "$*"; } - log_warn() { printf "WARN: %s\n" "$*"; } - print_error() { printf "ERROR: %s\n" "$*"; } + base_std_log_debug() { :; } + base_std_log_error() { printf "ERROR: %s\n" "$*"; } + base_std_log_info() { printf "INFO: %s\n" "$*"; } + base_std_log_warn() { printf "WARN: %s\n" "$*"; } + base_std_print_error() { printf "ERROR: %s\n" "$*"; } source "$BASE_REPO_ROOT/cli/bash/commands/basectl/subcommands/update.sh" base_update_run_homebrew_setup() { printf "setup should not run\n"; return 99; } base_update_subcommand_main @@ -433,11 +433,11 @@ EOF BASE_REPO_ROOT="$BASE_REPO_ROOT" \ PATH="$fake_bin:/usr/bin:/bin:/usr/sbin:/sbin" \ bash -c ' - log_debug() { :; } - log_error() { printf "ERROR: %s\n" "$*"; } - log_info() { printf "INFO: %s\n" "$*"; } - log_warn() { printf "WARN: %s\n" "$*"; } - print_error() { printf "ERROR: %s\n" "$*"; } + base_std_log_debug() { :; } + base_std_log_error() { printf "ERROR: %s\n" "$*"; } + base_std_log_info() { printf "INFO: %s\n" "$*"; } + base_std_log_warn() { printf "WARN: %s\n" "$*"; } + base_std_print_error() { printf "ERROR: %s\n" "$*"; } source "$BASE_REPO_ROOT/cli/bash/commands/basectl/subcommands/update.sh" base_update_subcommand_main ' @@ -458,7 +458,7 @@ EOF base_update_default_branch() { printf "%s\n" master; } base_update_worktree_clean() { return 1; } base_update_source_git_library() { printf "git library should not load\n"; return 99; } - git_update_repo() { printf "git update should not run\n"; return 99; } + base_git_update_repo() { printf "git update should not run\n"; return 99; } base_update_run_setup() { printf "setup should not run\n"; return 99; } base_update_subcommand_main ' @@ -492,7 +492,7 @@ EOF source "$BASE_HOME/base_init.sh" source "$BASE_HOME/cli/bash/commands/basectl/subcommands/update.sh" base_update_source_git_library() { :; } - git_update_repo() { printf "git update repo=%s branch=%s\n" "$1" "$3"; } + base_git_update_repo() { printf "git update repo=%s branch=%s\n" "$1" "$3"; } base_update_head_revision() { if [[ -f "$BASE_TEST_AFTER_UPDATE" ]]; then printf "%s\n" new5678 @@ -544,7 +544,7 @@ EOF base_update_worktree_clean() { return 0; } base_update_has_untracked_files() { return 1; } base_update_source_git_library() { :; } - git_update_repo() { printf "git update repo=%s branch=%s\n" "$1" "$3"; } + base_git_update_repo() { printf "git update repo=%s branch=%s\n" "$1" "$3"; } base_update_head_revision() { printf "%s\n" abc1234; } base_update_run_setup() { printf "setup should not run\n"; return 99; } base_update_subcommand_main @@ -571,7 +571,7 @@ EOF base_update_worktree_clean() { return 0; } base_update_has_untracked_files() { return 1; } base_update_source_git_library() { :; } - git_update_repo() { printf "git update repo=%s branch=%s\n" "$1" "$3"; } + base_git_update_repo() { printf "git update repo=%s branch=%s\n" "$1" "$3"; } base_update_head_revision() { if [[ -f "$BASE_TEST_AFTER_UPDATE" ]]; then printf "%s\n" new5678 @@ -614,7 +614,7 @@ EOF base_update_worktree_clean() { return 0; } base_update_has_untracked_files() { return 1; } base_update_source_git_library() { :; } - git_update_repo() { printf "git update repo=%s branch=%s\n" "$1" "$3"; } + base_git_update_repo() { printf "git update repo=%s branch=%s\n" "$1" "$3"; } base_update_head_revision() { if [[ -f "$BASE_TEST_AFTER_UPDATE" ]]; then printf "%s\n" new5678 diff --git a/docs/base-bash-libs.md b/docs/base-bash-libs.md index f396fd8c..c096e42a 100644 --- a/docs/base-bash-libs.md +++ b/docs/base-bash-libs.md @@ -129,9 +129,10 @@ diagnostics can report which external path won: `explicit`, `sibling`, or looks like a Homebrew Base install. An explicit `BASE_BASH_LIBS_DIR` must contain `std/lib_std.sh`, and the loaded -package must be from the corrected 1.x release line at version 1.3.0 or newer. -Base rejects stale 1.x checkouts and incompatible major-version checkouts during -runtime bootstrap with a direct diagnostic. If no explicit, sibling, or +package must provide the v2 `base_` namespace. During the coordinated release +train Base accepts the v2 API from the 1.4.0 development artifact; the final +v2 cutover raises the minimum package version to 2.0.0. Base rejects stale +checkouts during runtime bootstrap with a direct diagnostic. If no explicit, sibling, or Homebrew source is available, Base fails during runtime bootstrap with an actionable install or checkout message. The variable is intended for tests and nonstandard source worktree development. Users should not set it in `~/.baserc`, @@ -167,13 +168,13 @@ The Base contract is external-required: - Base consumes `base-bash-libs` from a sibling checkout during source development. -- Nonstandard worktrees can set `BASE_BASH_LIBS_DIR` to a compatible 1.x - `base-bash-libs/lib/bash` directory at version 1.3.0 or newer before runtime - bootstrap. +- Nonstandard worktrees can set `BASE_BASH_LIBS_DIR` to a `base-bash-libs/lib/bash` + directory that provides the v2 `base_` API before runtime bootstrap. - Homebrew Base consumes the Homebrew `base-bash-libs` package declared by the tap formula. -- Base CI pins the source checkout to the immutable `base-bash-libs` v1.4.0 - release commit; runtime compatibility remains a 1.x minimum-version contract. +- Base CI pins the source checkout to an immutable `base-bash-libs` commit. The + runtime contract is the v2 `base_` API, with the 2.0.0 version floor applied + at the final coordinated cutover. - `basectl check` and `basectl doctor` emit `BASE-D007` as ok when the external source is explicit, sibling, or Homebrew. - CI checks out `base-bash-libs` and validates Base without bundled reusable diff --git a/docs/execution-model.md b/docs/execution-model.md index 8269ed60..bd877b79 100644 --- a/docs/execution-model.md +++ b/docs/execution-model.md @@ -114,8 +114,9 @@ argument. `basectl` then: 5. sources the script 6. calls `main` with the remaining user arguments -This makes Base stdlib helpers such as `log_info`, `print_error`, -`fatal_error`, `run`, `assert_command_exists`, and `import_base_lib` available +This makes Base stdlib helpers such as `base_std_log_info`, `base_std_print_error`, +`base_std_fatal_error`, `base_std_run`, `base_std_assert_command_exists`, and +`import_base_lib` available without the script sourcing `lib_std.sh` directly. Standalone Bash scripts that are not intended to run through Base should use the @@ -173,7 +174,7 @@ list is `basectl --help`; this list summarizes the shipped public surface: - `activate` - `test` - `build` -- `run` +- `base_std_run` - `demo` - `repo` - `release` diff --git a/docs/runtime-environment.md b/docs/runtime-environment.md index 7a823e9d..1dbb9eba 100644 --- a/docs/runtime-environment.md +++ b/docs/runtime-environment.md @@ -74,7 +74,7 @@ explicit Bash script, or starts a Base runtime Bash shell. | `BASE_BASH_COMMANDS_DIR` | Base | `$BASE_BASH_DIR/commands`. Directory used by command dispatch. | Do not set. Readonly after `base_init.sh`. | | `BASE_LIB_DIR` | Base | `$BASE_HOME/lib`. Root for shared Base libraries. | Do not set. Readonly after `base_init.sh`. | | `BASE_BASH_LIB_DIR` | Base | `$BASE_HOME/lib/bash`. Base-specific Bash helper root, including runtime and version helpers. | Do not set. Readonly after `base_init.sh`. | -| `BASE_BASH_LIBS_DIR` | Base | Resolved reusable Bash library root used for stdlib loading and `import_base_lib`. It can point at an explicit `BASE_BASH_LIBS_DIR`, a sibling `base-bash-libs` checkout, or a Homebrew `base-bash-libs` package next to Homebrew Base. Base requires the corrected 1.x release line at version 1.3.0 or newer. | May be provided only before runtime bootstrap to force a compatible reusable library root. Readonly after `base_init.sh`. | +| `BASE_BASH_LIBS_DIR` | Base | Resolved reusable Bash library root used for stdlib loading and `import_base_lib`. It can point at an explicit `BASE_BASH_LIBS_DIR`, a sibling `base-bash-libs` checkout, or a Homebrew `base-bash-libs` package next to Homebrew Base. Base requires the v2 `base_` API; the final coordinated cutover applies the 2.0.0 version floor. | May be provided only before runtime bootstrap to force a compatible reusable library root. Readonly after `base_init.sh`. | | `BASE_BASH_LIBS_SOURCE` | Base | Source category for `BASE_BASH_LIBS_DIR`: `explicit`, `sibling`, or `homebrew`. `basectl check` and `basectl doctor` use this to report how Base is consuming external reusable Bash libraries. | Do not set. Readonly after `base_init.sh`. | | `BASE_CLI_SOURCE` | Base | Resolved `base_cli` provider: `explicit`, `sibling`, or `pip` after the standalone package is installed. | Do not set. Derived by Base before Python runtime startup. | | `BASE_SHELL_DIR` | Base | `$BASE_HOME/lib/shell`. Root for managed shell startup snippets and completions. | Do not set. Readonly after `base_init.sh`. | @@ -121,7 +121,7 @@ script path. They describe the script being dispatched, not the user's project. | `BASE_BASH_COMMAND_NAME` | Base | Normalized command name, such as `basectl` or a script basename without `.sh`. | Do not set. Readonly before the command script is sourced. | | `BASE_BASH_COMMAND_DIR` | Base | Physical directory containing the dispatched Bash script. | Do not set. Readonly before the command script is sourced. | | `BASE_BASH_COMMAND_SCRIPT` | Base | Physical path of the dispatched Bash script. | Do not set. Readonly before the command script is sourced. | -| `BASE_BASH_BOOTSTRAP_SOURCE` | Base | Internal transient override used while `base_init.sh` loads the Bash stdlib so `__SCRIPT_DIR__` resolves to the command script. | Do not set. It is unset immediately after bootstrap and is not part of the public runtime contract. | +| `BASE_BASH_LIBS_BOOTSTRAP_SOURCE` | Base | Internal transient override used while `base_init.sh` initializes the Bash stdlib so the v2 runtime source directory resolves to the command script. | Do not set. It is unset immediately after bootstrap and is not part of the public runtime contract. | ## Cache And Run Variables diff --git a/lib/bash/runtime/bashrc b/lib/bash/runtime/bashrc index a5e9434b..bb62ad75 100644 --- a/lib/bash/runtime/bashrc +++ b/lib/bash/runtime/bashrc @@ -251,6 +251,7 @@ _base_runtime_release_launcher_context() { BASE_CLI_RUN_ID \ BASE_CLI_RUN_ROOT \ BASE_CLI_PRIMARY_LOG \ + BASE_BASH_LIBS_PRIMARY_LOG \ BASE_CLI_HISTORY_PARENT_RUN_ID \ BASE_CLI_HISTORY_STARTED_AT \ BASE_CLI_HISTORY_SCOPE \ diff --git a/tests/base_init.bats b/tests/base_init.bats index 986e7231..bae2a7f8 100644 --- a/tests/base_init.bats +++ b/tests/base_init.bats @@ -114,11 +114,11 @@ EOF ' [ "$status" -ne 0 ] - [[ "$output" == *"base-bash-libs 1.3.0 or newer is required"* ]] - [[ "$output" == *"loaded version is 1.2.0"* ]] + [[ "$output" == *"Base requires base-bash-libs 1.4.0 or newer"* ]] + [[ "$output" == *"loaded version is '1.2.0'"* ]] } -@test "base_init rejects an incompatible base-bash-libs major release" { +@test "base_init accepts the v2 base-bash-libs namespace during the cutover" { printf '2.0.0\n' > "$TEST_TMPDIR/base-bash-libs/VERSION" run_base_init_script ' @@ -126,9 +126,7 @@ EOF source "$base_home/base_init.sh" ' - [ "$status" -ne 0 ] - [[ "$output" == *"Base requires base-bash-libs 1.3.0 or a compatible later 1.x release"* ]] - [[ "$output" == *"loaded version is '2.0.0'"* ]] + [ "$status" -eq 0 ] } @test "base_init preserves explicit symlinked BASE_HOME paths" { @@ -395,7 +393,7 @@ EOF base_home="$1" source "$base_home/base_init.sh" source "$base_home/base_init.sh" - print_path | grep -Fxc "$BASE_BIN_DIR" + base_std_print_path | grep -Fxc "$BASE_BIN_DIR" ' [ "$status" -eq 0 ] @@ -407,7 +405,7 @@ EOF base_home="$1" source "$base_home/base_init.sh" import_base_lib file/lib_file.sh - declare -F safe_touch >/dev/null + declare -F base_std_safe_touch >/dev/null ' [ "$status" -eq 0 ] diff --git a/tests/base_test.bats b/tests/base_test.bats index 90b9e02f..71142b7b 100644 --- a/tests/base_test.bats +++ b/tests/base_test.bats @@ -60,7 +60,7 @@ for name in \ BASE_CLI_RUNTIME_OWNER \ BASE_CLI_RUN_ID \ BASE_CLI_RUN_ROOT \ - BASE_CLI_PRIMARY_LOG \ + BASE_BASH_LIBS_PRIMARY_LOG \ BASE_CLI_HISTORY_PARENT_RUN_ID \ BASE_CLI_HISTORY_SCOPE \ BASE_CLI_PROJECT_NAME \ @@ -195,7 +195,7 @@ EOF BASE_CLI_RUNTIME_OWNER=project \ BASE_CLI_RUN_ID=parent-run \ BASE_CLI_RUN_ROOT="$TEST_TMPDIR/parent-run" \ - BASE_CLI_PRIMARY_LOG="$TEST_TMPDIR/parent-run/logs/primary.log" \ + BASE_BASH_LIBS_PRIMARY_LOG="$TEST_TMPDIR/parent-run/logs/primary.log" \ BASE_CLI_HISTORY_PARENT_RUN_ID=parent-run \ BASE_CLI_HISTORY_SCOPE=internal \ BASE_CLI_PROJECT_NAME=base \ @@ -214,7 +214,7 @@ EOF BASE_CLI_RUNTIME_OWNER \ BASE_CLI_RUN_ID \ BASE_CLI_RUN_ROOT \ - BASE_CLI_PRIMARY_LOG \ + BASE_BASH_LIBS_PRIMARY_LOG \ BASE_CLI_HISTORY_PARENT_RUN_ID \ BASE_CLI_HISTORY_SCOPE \ BASE_CLI_PROJECT_NAME \ diff --git a/tests/test_helper.sh b/tests/test_helper.sh index b2e86dd8..5f87e786 100644 --- a/tests/test_helper.sh +++ b/tests/test_helper.sh @@ -39,7 +39,7 @@ unset_base_runtime_env() { BASE_BASH_COMMAND_NAME \ BASE_BASH_COMMAND_DIR \ BASE_BASH_COMMAND_SCRIPT \ - BASE_BASH_BOOTSTRAP_SOURCE \ + BASE_BASH_LIBS_BOOTSTRAP_SOURCE \ BASE_INIT_TEST_OS_RELEASE_PATH \ BASE_INIT_TEST_KERNEL_OSRELEASE_PATH \ BASE_INIT_TEST_PROC_VERSION_PATH \