-
Notifications
You must be signed in to change notification settings - Fork 5
fix: suppress stdout pollution in create_task_worktree (t169, t173) #643
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -992,6 +992,68 @@ else | |||||||||||||||||||||||||||||||||||||||||||
| fail "Exit 0 with error strings should NOT be blocked" "Got: $eval_result" | ||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| # ============================================================ | ||||||||||||||||||||||||||||||||||||||||||||
| # SECTION 7: Worktree Path Integrity | ||||||||||||||||||||||||||||||||||||||||||||
| # ============================================================ | ||||||||||||||||||||||||||||||||||||||||||||
| section "Worktree Path Integrity" | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| # Test: create_task_worktree returns a clean single-line path (no stdout pollution) | ||||||||||||||||||||||||||||||||||||||||||||
| # This is a regression test for the bug where `git branch -D` output ("Deleted branch ...") | ||||||||||||||||||||||||||||||||||||||||||||
| # leaked into the function's return value, causing dispatch to fail with invalid paths. | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| WORKTREE_TEST_DIR=$(mktemp -d) | ||||||||||||||||||||||||||||||||||||||||||||
| WORKTREE_TEST_REPO="$WORKTREE_TEST_DIR/test-repo" | ||||||||||||||||||||||||||||||||||||||||||||
| trap 'rm -rf "$WORKTREE_TEST_DIR"; rm -rf "$TEST_DIR"' EXIT | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| # Set up a minimal git repo for worktree testing | ||||||||||||||||||||||||||||||||||||||||||||
| git init "$WORKTREE_TEST_REPO" &>/dev/null | ||||||||||||||||||||||||||||||||||||||||||||
| git -C "$WORKTREE_TEST_REPO" commit --allow-empty -m "initial" &>/dev/null | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| # Create a branch that will need cleanup (simulates stale branch from prior failed dispatch) | ||||||||||||||||||||||||||||||||||||||||||||
| git -C "$WORKTREE_TEST_REPO" branch "feature/wt-test-001" &>/dev/null | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| # Add task to supervisor DB | ||||||||||||||||||||||||||||||||||||||||||||
| sup add wt-test-001 --repo "$WORKTREE_TEST_REPO" --description "Worktree stdout leak test" >/dev/null 2>&1 || true | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| # Call create_task_worktree directly. The script calls main "$@" at the bottom | ||||||||||||||||||||||||||||||||||||||||||||
| # when sourced, so we pass "init" to avoid show_usage. We redirect the source's | ||||||||||||||||||||||||||||||||||||||||||||
| # stdout to /dev/null (suppresses cmd_init output) — function definitions still | ||||||||||||||||||||||||||||||||||||||||||||
| # register in the current shell. Then we call the function we want to test. | ||||||||||||||||||||||||||||||||||||||||||||
| worktree_output=$(bash -c " | ||||||||||||||||||||||||||||||||||||||||||||
| export AIDEVOPS_SUPERVISOR_DIR='$TEST_DIR' | ||||||||||||||||||||||||||||||||||||||||||||
| set -- init | ||||||||||||||||||||||||||||||||||||||||||||
| source '$SUPERVISOR_SCRIPT' >/dev/null | ||||||||||||||||||||||||||||||||||||||||||||
| create_task_worktree 'wt-test-001' '$WORKTREE_TEST_REPO' true | ||||||||||||||||||||||||||||||||||||||||||||
| " 2>/dev/null) | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| # Count lines — should be exactly 1 (the path) | ||||||||||||||||||||||||||||||||||||||||||||
| line_count=$(echo "$worktree_output" | wc -l | tr -d ' ') | ||||||||||||||||||||||||||||||||||||||||||||
| if [[ "$line_count" -eq 1 ]]; then | ||||||||||||||||||||||||||||||||||||||||||||
| pass "create_task_worktree returns exactly 1 line (no stdout pollution)" | ||||||||||||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||||||||||||
| fail "create_task_worktree returned $line_count lines (stdout pollution detected)" \ | ||||||||||||||||||||||||||||||||||||||||||||
| "Output: $(echo "$worktree_output" | head -3)" | ||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+1029
to
+1036
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Empty output passes the "exactly 1 line" check — false-positive risk. If 🐛 Proposed fix+# Guard: empty output is an immediate failure
+if [[ -z "$worktree_output" ]]; then
+ fail "create_task_worktree returned empty output"
+else
# Count lines — should be exactly 1 (the path)
line_count=$(echo "$worktree_output" | wc -l | tr -d ' ')
if [[ "$line_count" -eq 1 ]]; then
pass "create_task_worktree returns exactly 1 line (no stdout pollution)"
else
fail "create_task_worktree returned $line_count lines (stdout pollution detected)" \
"Output: $(echo "$worktree_output" | head -3)"
fi
+fi📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| # Verify the returned path is a real directory | ||||||||||||||||||||||||||||||||||||||||||||
| if [[ -d "$worktree_output" ]]; then | ||||||||||||||||||||||||||||||||||||||||||||
| pass "create_task_worktree returns a valid directory path" | ||||||||||||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||||||||||||
| fail "create_task_worktree path is not a directory" "Got: '$worktree_output'" | ||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| # Verify path doesn't contain "Deleted branch" (the specific pollution we fixed) | ||||||||||||||||||||||||||||||||||||||||||||
| if echo "$worktree_output" | grep -qi "deleted branch"; then | ||||||||||||||||||||||||||||||||||||||||||||
| fail "create_task_worktree output contains 'Deleted branch' pollution" \ | ||||||||||||||||||||||||||||||||||||||||||||
| "Got: '$worktree_output'" | ||||||||||||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||||||||||||
| pass "create_task_worktree output is free of 'Deleted branch' pollution" | ||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| # Clean up the test worktree | ||||||||||||||||||||||||||||||||||||||||||||
| git -C "$WORKTREE_TEST_REPO" worktree remove "$worktree_output" --force &>/dev/null || rm -rf "$worktree_output" | ||||||||||||||||||||||||||||||||||||||||||||
| git -C "$WORKTREE_TEST_REPO" worktree prune &>/dev/null || true | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| # ============================================================ | ||||||||||||||||||||||||||||||||||||||||||||
| # SUMMARY | ||||||||||||||||||||||||||||||||||||||||||||
| # ============================================================ | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: marcusquinn/aidevops
Length of output: 234
🏁 Script executed:
# Read the test file around the flagged lines wc -l tests/test-supervisor-state-machine.shRepository: marcusquinn/aidevops
Length of output: 107
🏁 Script executed:
Repository: marcusquinn/aidevops
Length of output: 185
🏁 Script executed:
Repository: marcusquinn/aidevops
Length of output: 1104
🏁 Script executed:
Repository: marcusquinn/aidevops
Length of output: 107
🏁 Script executed:
Repository: marcusquinn/aidevops
Length of output: 78
🏁 Script executed:
Repository: marcusquinn/aidevops
Length of output: 116
🏁 Script executed:
Repository: marcusquinn/aidevops
Length of output: 1368
🏁 Script executed:
Repository: marcusquinn/aidevops
Length of output: 1341
🏁 Script executed:
Repository: marcusquinn/aidevops
Length of output: 77
🏁 Script executed:
Repository: marcusquinn/aidevops
Length of output: 372
🏁 Script executed:
Repository: marcusquinn/aidevops
Length of output: 81
🏁 Script executed:
Repository: marcusquinn/aidevops
Length of output: 93
🏁 Script executed:
Repository: marcusquinn/aidevops
Length of output: 2391
🏁 Script executed:
Repository: marcusquinn/aidevops
Length of output: 2987
🏁 Script executed:
Repository: marcusquinn/aidevops
Length of output: 487
🏁 Script executed:
Repository: marcusquinn/aidevops
Length of output: 3970
🏁 Script executed:
Repository: marcusquinn/aidevops
Length of output: 487
🏁 Script executed:
Repository: marcusquinn/aidevops
Length of output: 467
🏁 Script executed:
Repository: marcusquinn/aidevops
Length of output: 487
🏁 Script executed:
Repository: marcusquinn/aidevops
Length of output: 1510
🏁 Script executed:
Repository: marcusquinn/aidevops
Length of output: 968
Error suppression masks whether
cmd_init/ database initialization actually succeeded — test can pass even if DB is non-functional.The
set -- initworkaround is necessary and already well-documented in the preceding comment. However, the actual risk is deeper:cmd_initcallsensure_dbwithout checking its return code (line 906 of supervisor-helper.sh), and both stdout and stderr from sourcing are redirected away. Ifensure_dbfails silently (e.g., DB initialization fails but doesn't exit),cmd_initcontinues and returns 0.More importantly,
create_task_worktreeoperates only on git state (worktrees/branches), not the database — so the test can pass and return a valid directory path even if the supervisor database was never initialized. This test validates that function definitions load andcreate_task_worktreereturns no extraneous stdout, but provides no assurance the supervisor DB is actually ready when the function runs.Consider adding an explicit DB validation step (e.g., verify
$SUPERVISOR_DBexists and can execute a simple query) before or after callingcreate_task_worktreeto catch silent initialization failures.🤖 Prompt for AI Agents