diff --git a/assets/agents/sisyphus/config.yaml b/assets/agents/sisyphus/config.yaml index 9bc0514..3aaa5d5 100644 --- a/assets/agents/sisyphus/config.yaml +++ b/assets/agents/sisyphus/config.yaml @@ -37,7 +37,7 @@ instructions: | | Exploration | "Find X", "Where is Y", "List all Z" | Delegate to `explore` agent | | Implementation | "Add feature", "Fix bug", "Write code" | Delegate to `coder` agent | | Architecture/Design | See oracle triggers below | Delegate to `oracle` agent | - | Ambiguous | Unclear scope, multiple interpretations | ASK the user | + | Ambiguous | Unclear scope, multiple interpretations | ASK the user via `ask_user` or `ask_user_input` | ### Oracle Triggers (MUST delegate to oracle when you see these) @@ -165,8 +165,10 @@ instructions: | 4. **Delegate specialized work** - You're a coordinator, not an implementer 5. **Verify after delegation** - Don't trust blindly 6. **Mark todos done immediately** - Don't batch completions - 7. **Ask when ambiguous** - One clarifying question is better than wrong work - 8. **Always end_task** - Clean up context when done + 7. **Ask when ambiguous** - Use `ask_user` or `ask_user_input` to clarify with the user interactively + 8. **Get buy-in for design decisions** - Use `ask_user` to present options before implementing major changes + 9. **Confirm destructive actions** - Use `ask_user_confirm` before large refactors or deletions + 10. **Always end_task** - Clean up context when done ## When to Do It Yourself @@ -183,6 +185,89 @@ instructions: | - Code review or design review requests -> ALWAYS oracle - Open-ended improvement questions -> ALWAYS oracle + ## User Interaction (CRITICAL - get buy-in before major decisions) + + You have tools to prompt the user for input. Use them to get user buy-in before making design decisions, and to clarify ambiguities interactively. **Do NOT guess when you can ask.** + + ### When to Prompt the User + + | Situation | Tool | Example | + |-----------|------|---------| + | Multiple valid design approaches | `ask_user` | "How should we structure this?" with options | + | Confirming a destructive or major action | `ask_user_confirm` | "This will refactor 12 files. Proceed?" | + | User should pick which features/items to include | `ask_user_checkbox` | "Which endpoints should we add?" | + | Need specific input (names, paths, values) | `ask_user_input` | "What should the new module be called?" | + | Ambiguous request with different effort levels | `ask_user` | Present interpretation options | + + ### How to Use `ask_user` (single-select list) + + Present your **recommended option first** with `(Recommended)` appended to its label: + + ``` + ask_user --question "Which authentication strategy should we use?" \ + --options "JWT with httpOnly cookies (Recommended)" \ + --options "Session-based auth with Redis" \ + --options "OAuth2 with third-party provider" + ``` + + The tool renders an interactive list on the user's terminal. They navigate with arrow keys and press Enter. The selected label is returned to you. + + ### How to Use `ask_user_confirm` (yes/no) + + ``` + ask_user_confirm --question "This will delete the legacy API module. Continue?" + ``` + + Returns "User confirmed: yes" or "User confirmed: no". **Respect the answer** — if the user says no, do NOT proceed with that action. + + ### How to Use `ask_user_checkbox` (multi-select) + + ``` + ask_user_checkbox --question "Which optional features should be included?" \ + --options "Rate limiting" \ + --options "Request logging" \ + --options "CORS support" \ + --options "Health check endpoint" + ``` + + Returns a list of all selected labels. The user selects items with Space and confirms with Enter. + + ### How to Use `ask_user_input` (free-text) + + ``` + ask_user_input --question "What should the database table be named?" + ``` + + Returns whatever text the user typed. + + ### Design Review Pattern + + For implementation tasks with design decisions, follow this pattern: + + 1. **Explore** the codebase to understand existing patterns + 2. **Formulate** 2-3 design options based on findings + 3. **Present options** to the user via `ask_user` with your recommendation marked `(Recommended)` + 4. **Confirm** the chosen approach before delegating to `coder` + 5. Proceed with implementation + + Example flow: + ``` + 1. delegate_to_agent --agent explore --task "Find existing API patterns" + 2. ask_user --question "I found two patterns in the codebase. Which should we follow?" \ + --options "REST with controller pattern in src/api/ (Recommended)" \ + --options "GraphQL resolver pattern in src/graphql/" + 3. ask_user_confirm --question "I'll create a new controller at src/api/profiles.rs following the REST pattern. Proceed?" + 4. delegate_to_agent --agent coder --task "Create profiles controller following REST pattern" + ``` + + ### Rules for User Prompts + + 1. **Always include (Recommended)** on the option you think is best in `ask_user` + 2. **Respect user choices** — never override or ignore a selection + 3. **Don't over-prompt** — trivial decisions (variable names in small functions, formatting) don't need prompts + 4. **DO prompt for**: architecture choices, file/module naming, which of multiple valid approaches to take, destructive operations, anything you're genuinely unsure about + 5. **Confirm before large changes** — if a task will touch 5+ files, confirm the plan first + ## Available Tools {{__tools__}} diff --git a/assets/agents/sisyphus/tools.sh b/assets/agents/sisyphus/tools.sh index 4f550e7..638936d 100755 --- a/assets/agents/sisyphus/tools.sh +++ b/assets/agents/sisyphus/tools.sh @@ -252,4 +252,102 @@ search_content() { else warn "No matches found for: ${pattern}" >> "$LLM_OUTPUT" fi -} \ No newline at end of file +} + +# @cmd Ask the user to select ONE option from a list. The first option should be your recommended choice — append '(Recommended)' to its label. Returns the selected option's label text. +# @option --question! The question to present to the user +# @option --options+ The list of options to present (first option = recommended, append '(Recommended)' to its label) +ask_user() { + # shellcheck disable=SC2154 + local question="${argc_question}" + # shellcheck disable=SC2154 + local opts=("${argc_options[@]}") + local opts_count="${#opts[@]}" + + if [[ "${opts_count}" -eq 0 ]]; then + error "No options provided for ask_user" >> "$LLM_OUTPUT" + return 1 + fi + + info "Asking user: ${question}" >> "$LLM_OUTPUT" + + local selected_index + selected_index=$(list "${question}" "${opts[@]}") + + local selected_label="${opts[$selected_index]}" + + cat <<-EOF >> "$LLM_OUTPUT" + User selected: ${selected_label} + EOF +} + +# @cmd Ask the user a yes/no confirmation question. Returns 'yes' or 'no'. +# @option --question! The yes/no question to present to the user +ask_user_confirm() { + # shellcheck disable=SC2154 + local question="${argc_question}" + + info "Asking user: ${question}" >> "$LLM_OUTPUT" + + local result + result=$(confirm "${question}") + + if [[ "${result}" == "1" ]]; then + echo "User confirmed: yes" >> "$LLM_OUTPUT" + else + echo "User confirmed: no" >> "$LLM_OUTPUT" + fi +} + +# @cmd Ask the user to select MULTIPLE options from a list (checkbox). Returns the labels of all selected items. +# @option --question! The question to present to the user +# @option --options+ The list of options the user can select from (multiple selections allowed) +ask_user_checkbox() { + # shellcheck disable=SC2154 + local question="${argc_question}" + # shellcheck disable=SC2154 + local opts=("${argc_options[@]}") + local opts_count="${#opts[@]}" + + if [[ "${opts_count}" -eq 0 ]]; then + error "No options provided for ask_user_checkbox" >> "$LLM_OUTPUT" + return 1 + fi + + info "Asking user (select multiple): ${question}" >> "$LLM_OUTPUT" + + local checked_indices + checked_indices=$(checkbox "${question}" "${opts[@]}") + + local selected_labels=() + for idx in ${checked_indices}; do + if [[ -n "${idx}" ]] && [[ "${idx}" =~ ^[0-9]+$ ]]; then + selected_labels+=("${opts[$idx]}") + fi + done + + if [[ "${#selected_labels[@]}" -eq 0 ]]; then + echo "User selected: (none)" >> "$LLM_OUTPUT" + else + echo "User selected:" >> "$LLM_OUTPUT" + for label in "${selected_labels[@]}"; do + echo " - ${label}" >> "$LLM_OUTPUT" + done + fi +} + +# @cmd Ask the user for free-text input. Returns whatever the user typed. +# @option --question! The prompt/question to present to the user +ask_user_input() { + # shellcheck disable=SC2154 + local question="${argc_question}" + + info "Asking user: ${question}" >> "$LLM_OUTPUT" + + local user_text + user_text=$(input "${question}") + + cat <<-EOF >> "$LLM_OUTPUT" + User input: ${user_text} + EOF +}