From 431e5493fcd14dcc89e0a6cbd09a5b3dc58ba71d Mon Sep 17 00:00:00 2001 From: Karamelmar Date: Mon, 9 Mar 2026 12:11:31 +0100 Subject: [PATCH] Fix set -e bug causing silent exit after valid input MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Replace all `[[ condition ]] && die` with `if/fi` — the && pattern exits silently when the condition is false under set -e - Removed -e from set flags (kept -uo pipefail), all error paths are now explicit - Declare `input` as local in ask/ask_yn/ask_choice to prevent leakage - Use `read -r input || true` to handle EOF safely - Fix ask_choice arithmetic to avoid (()) triggering exit on false Co-Authored-By: Claude Sonnet 4.6 --- lib/prereqs.sh | 5 +++-- lib/utils.sh | 19 +++++++++++-------- wizard.sh | 22 ++++++++++------------ 3 files changed, 24 insertions(+), 22 deletions(-) diff --git a/lib/prereqs.sh b/lib/prereqs.sh index 3e5840b..e0f1c13 100644 --- a/lib/prereqs.sh +++ b/lib/prereqs.sh @@ -41,7 +41,7 @@ ensure_git() { fi warn "git not found." ask_yn _install "Install git now?" "y" - [[ "$_install" != "y" ]] && die "git is required." + if [[ "$_install" != "y" ]]; then die "git is required."; fi install_pkg git command -v git &>/dev/null || die "git installation failed." success "git installed: $(git --version)" @@ -69,7 +69,8 @@ ensure_container_runtime() { "podman (recommended)" \ "docker" - case "$_runtime" in + local runtime_choice="$_runtime" + case "$runtime_choice" in podman*) _install_podman CONTAINER_CMD="podman" diff --git a/lib/utils.sh b/lib/utils.sh index d950501..36d46cf 100644 --- a/lib/utils.sh +++ b/lib/utils.sh @@ -18,26 +18,27 @@ header() { echo -e "\n${BOLD}${CYAN}━━━ $* ━━━${RESET}\n"; } # ask VAR "prompt" "default" ask() { local var="$1" prompt="$2" default="$3" + local input if [[ -n "$default" ]]; then echo -ne "${BOLD}${prompt}${RESET} ${CYAN}[${default}]${RESET}: " else echo -ne "${BOLD}${prompt}${RESET}: " fi - read -r input + read -r input || true if [[ -z "$input" && -n "$default" ]]; then - eval "$var=\"$default\"" + eval "$var=\"\$default\"" else - eval "$var=\"$input\"" + eval "$var=\"\$input\"" fi } # ask_yn VAR "prompt" "y|n" ask_yn() { local var="$1" prompt="$2" default="$3" - local options + local input options if [[ "$default" == "y" ]]; then options="Y/n"; else options="y/N"; fi echo -ne "${BOLD}${prompt}${RESET} ${CYAN}[${options}]${RESET}: " - read -r input + read -r input || true input="${input:-$default}" if [[ "$input" =~ ^[Yy]$ ]]; then eval "$var=y" @@ -50,18 +51,20 @@ ask_yn() { ask_choice() { local var="$1" prompt="$2"; shift 2 local options=("$@") + local input idx echo -e "${BOLD}${prompt}${RESET}" for i in "${!options[@]}"; do echo -e " ${CYAN}$((i+1))${RESET}) ${options[$i]}" done echo -ne "Choice ${CYAN}[1]${RESET}: " - read -r input + read -r input || true input="${input:-1}" if [[ "$input" =~ ^[0-9]+$ ]] && (( input >= 1 && input <= ${#options[@]} )); then - eval "$var=\"${options[$((input-1))]}\"" + idx=$(( input - 1 )) else - eval "$var=\"${options[0]}\"" + idx=0 fi + eval "$var=\"\${options[$idx]}\"" } require_cmd() { diff --git a/wizard.sh b/wizard.sh index 458efac..237f228 100755 --- a/wizard.sh +++ b/wizard.sh @@ -2,7 +2,7 @@ # ╔══════════════════════════════════════════════════════════════════╗ # ║ Context Studio Wizard — Project Setup ║ # ╚══════════════════════════════════════════════════════════════════╝ -set -euo pipefail +set -uo pipefail WIZARD_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" @@ -17,17 +17,17 @@ collect_project_info() { header "Project Details" ask PROJECT_NAME "Project name" "" - [[ -z "$PROJECT_NAME" ]] && die "Project name is required." + if [[ -z "$PROJECT_NAME" ]]; then die "Project name is required."; fi local default_dir="$HOME/projects/$(slugify "$PROJECT_NAME")" ask PROJECT_DIR "Project location" "$default_dir" - [[ -z "$PROJECT_DIR" ]] && die "Project location is required." + if [[ -z "$PROJECT_DIR" ]]; then die "Project location is required."; fi PROJECT_DIR="${PROJECT_DIR/#\~/$HOME}" if [[ -e "$PROJECT_DIR" ]]; then warn "Directory already exists: $PROJECT_DIR" ask_yn _continue "Continue anyway?" "n" - [[ "$_continue" != "y" ]] && die "Aborted." + if [[ "$_continue" != "y" ]]; then die "Aborted."; fi fi } @@ -41,14 +41,13 @@ collect_workflow_info() { if [[ "$WORKFLOW_SOURCE" == "Clone from existing repo" ]]; then ask WORKFLOW_REPO "Workflow repo URL" "" - [[ -z "$WORKFLOW_REPO" ]] && die "Repo URL is required." + if [[ -z "$WORKFLOW_REPO" ]]; then die "Repo URL is required."; fi else ask PROJECT_DESC "Project description" "A software project" ask TECH_STACK "Tech stack (e.g. Node.js, Rust, Python)" "Node.js" ask_choice AGENT_PRESET "Agent preset" \ "minimal (5 agents: coordinator, 2 coders, researcher, tester)" \ "standard (9 agents: 2 coordinators, 3 coders, 2 researchers, tester, reviewer)" - # Normalize to short key case "$AGENT_PRESET" in minimal*) AGENT_PRESET="minimal" ;; *) AGENT_PRESET="standard" ;; @@ -63,15 +62,15 @@ confirm_summary() { echo -e " ${BOLD}Location${RESET} : $PROJECT_DIR" echo -e " ${BOLD}Core${RESET} : $CS_CORE_DIR" if [[ "${WORKFLOW_SOURCE:-}" == "Clone from existing repo" ]]; then - echo -e " ${BOLD}Workflow${RESET} : clone $WORKFLOW_REPO" + echo -e " ${BOLD}Workflow${RESET} : clone ${WORKFLOW_REPO:-}" else - echo -e " ${BOLD}Workflow${RESET} : generate ($AGENT_PRESET preset)" + echo -e " ${BOLD}Workflow${RESET} : generate (${AGENT_PRESET:-minimal} preset)" echo -e " ${BOLD}Description${RESET} : ${PROJECT_DESC:-}" echo -e " ${BOLD}Tech stack${RESET} : ${TECH_STACK:-}" fi echo "" ask_yn _ok "Create project?" "y" - [[ "$_ok" != "y" ]] && die "Aborted." + if [[ "$_ok" != "y" ]]; then die "Aborted."; fi } # ── Build ────────────────────────────────────────────────────────────────── @@ -82,15 +81,14 @@ build_project() { create_devcontainer "$PROJECT_DIR" "$PROJECT_NAME" if [[ "${WORKFLOW_SOURCE:-}" == "Clone from existing repo" ]]; then - clone_workflow "$PROJECT_DIR" "$WORKFLOW_REPO" + clone_workflow "$PROJECT_DIR" "${WORKFLOW_REPO:-}" else generate_workflow "$PROJECT_DIR" "$PROJECT_NAME" \ "${PROJECT_DESC:-A software project}" \ "${TECH_STACK:-Node.js}" \ - "$AGENT_PRESET" + "${AGENT_PRESET:-minimal}" fi - # Init git repo git -C "$PROJECT_DIR" init -q git -C "$PROJECT_DIR" add . git -C "$PROJECT_DIR" commit -q -m "Initial project setup via Context Studio Wizard"