Stop setup blocking on invisible sbx confirmation prompts
sbx skills import prompts before overwriting each skill already in the shared store. setup called it with stdout and stderr redirected and stdin left attached, so on any second run the prompt was invisible and setup hung indefinitely partway through installing the Claude configuration. sbx rm prompts the same way, which would have blocked --replace and remove once a sandbox was in use. Both now pass --force and read from /dev/null. This is the third instance of the pattern after sbx secret set, which cancelled silently and still exited 0, so a test now asserts at the source level that every prompting subcommand is invoked non-interactively. The test was confirmed to fail when either --force is removed.
This commit is contained in:
+6
-3
@@ -660,7 +660,10 @@ install_sandbox_claude_config() {
|
|||||||
|
|
||||||
# The store is shared by every sandbox, so this seeds all of them at once.
|
# The store is shared by every sandbox, so this seeds all of them at once.
|
||||||
if [[ -d "$CLAUDE_HOME/skills" ]]; then
|
if [[ -d "$CLAUDE_HOME/skills" ]]; then
|
||||||
sbx skills import >/dev/null 2>&1 ||
|
# --force is mandatory: the store is shared, so a second setup finds
|
||||||
|
# skills already there and prompts per skill. With output redirected
|
||||||
|
# the prompt is invisible and setup hangs on stdin forever.
|
||||||
|
sbx skills import --force </dev/null >/dev/null 2>&1 ||
|
||||||
printf 'Could not import skills into the shared store.\n' >&2
|
printf 'Could not import skills into the shared store.\n' >&2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -909,7 +912,7 @@ setup_command() {
|
|||||||
if sandbox_exists; then
|
if sandbox_exists; then
|
||||||
if [[ "$replace" == true ]]; then
|
if [[ "$replace" == true ]]; then
|
||||||
printf 'Removing existing sandbox %s...\n' "$SANDBOX_NAME"
|
printf 'Removing existing sandbox %s...\n' "$SANDBOX_NAME"
|
||||||
sbx rm "$SANDBOX_NAME"
|
sbx rm --force "$SANDBOX_NAME" </dev/null
|
||||||
else
|
else
|
||||||
printf 'Using existing sandbox %s.\n' "$SANDBOX_NAME"
|
printf 'Using existing sandbox %s.\n' "$SANDBOX_NAME"
|
||||||
fi
|
fi
|
||||||
@@ -1042,7 +1045,7 @@ remove_command() {
|
|||||||
load_config
|
load_config
|
||||||
|
|
||||||
if sandbox_exists; then
|
if sandbox_exists; then
|
||||||
sbx rm "$SANDBOX_NAME"
|
sbx rm --force "$SANDBOX_NAME" </dev/null
|
||||||
fi
|
fi
|
||||||
|
|
||||||
rm -rf "$REPO_CONFIG_DIR"
|
rm -rf "$REPO_CONFIG_DIR"
|
||||||
|
|||||||
Executable
+45
@@ -0,0 +1,45 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
TASK="$(dirname "${BASH_SOURCE[0]}")/../tasks/ai/sbx"
|
||||||
|
|
||||||
|
failures=0
|
||||||
|
|
||||||
|
fail() {
|
||||||
|
printf 'FAIL: %s\n' "$1" >&2
|
||||||
|
failures=$((failures + 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
code() {
|
||||||
|
grep -n '^[^#]*sbx ' "$TASK" | grep -v 'ai:sbx'
|
||||||
|
}
|
||||||
|
|
||||||
|
require_force() {
|
||||||
|
local pattern="$1" line
|
||||||
|
local found=false
|
||||||
|
|
||||||
|
while IFS= read -r line; do
|
||||||
|
found=true
|
||||||
|
[[ "$line" == *"--force"* ]] ||
|
||||||
|
fail "missing --force, will block on a prompt: ${line#*:}"
|
||||||
|
done < <(code | grep -F "$pattern" || true)
|
||||||
|
|
||||||
|
[[ "$found" == true ]] ||
|
||||||
|
fail "no invocation of '$pattern' found; has it been renamed?"
|
||||||
|
}
|
||||||
|
|
||||||
|
require_force 'sbx secret set'
|
||||||
|
require_force 'sbx skills import'
|
||||||
|
require_force 'sbx rm '
|
||||||
|
|
||||||
|
while IFS= read -r line; do
|
||||||
|
[[ "$line" == *"</dev/null"* ]] ||
|
||||||
|
fail "missing </dev/null: ${line#*:}"
|
||||||
|
done < <(code | grep -F 'sbx skills import' || true)
|
||||||
|
|
||||||
|
if ((failures)); then
|
||||||
|
printf '%d assertion(s) failed\n' "$failures" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf 'All non-interactive invocation assertions passed.\n'
|
||||||
Reference in New Issue
Block a user