Files
galaxy/specs/QUALITY-512-ask-user-question-speedbump/TECH.md
T

87 lines
6.5 KiB
Markdown

# Ask-User-Question Autonomy Speedbump — Technical Notes
Linear: [QUALITY-512](https://linear.app/warpdotdev/issue/QUALITY-512/add-ask-user-question-permission-speedbump)
Product spec: `specs/QUALITY-512-ask-user-question-speedbump/PRODUCT.md`
## 1. Overview
This change adds a one-shot Ask-User-Question autonomy speedbump to the existing `AIBlock` speedbump infrastructure. The speedbump installs a compact footer into `AskUserQuestionView`, backed by a `Dropdown<AIBlockAction>` that updates the active execution profile's `ask_user_question` permission.
## 2. Key files
- `app/src/settings/ai.rs` — defines `should_show_agent_mode_ask_user_question_speedbump` as a private local-only setting with `SyncToCloud::Never`.
- `app/src/ai/blocklist/block.rs` — seeds the new speedbump variant, owns the dropdown view, syncs the footer into `AskUserQuestionView`, handles dropdown actions, and consumes the one-shot flag after successful footer installation.
- `app/src/ai/blocklist/block/view_impl.rs` — renders the shared dropdown speedbump footer row.
- `app/src/ai/blocklist/inline_action/ask_user_question_view.rs` — owns the Ask-User-Question card chrome and renders the attached footer in completed/collapsed states.
- `app/src/server/telemetry/events.rs` — adds `ChangedAgentModeAskUserQuestionPermission`.
- `app/src/terminal/block_list_element.rs` — forwards covered mouse events to visible rich-content overlays so dropdown menus remain interactive.
- `crates/warpui_core/src/elements/dismiss.rs` — consumes underlay clicks for dismissable overlays that prevent interaction with other elements.
- `crates/warpui_core/src/elements/selectable_area.rs` — avoids starting terminal selection for mouse down events covered by higher-z-index overlays.
- `app/src/ai/blocklist/block_tests.rs` — covers permission index mapping, first Ask-User-Question action detection, and setting defaults/round-trip.
## 3. Setting
The new setting is intentionally local-only:
- Name: `should_show_agent_mode_ask_user_question_speedbump`
- Default: `true`
- Private: `true`
- Sync: `SyncToCloud::Never`
This keeps the speedbump display tied to the local client state. It also avoids cross-device races where one device could consume the onboarding display for another device.
## 4. Speedbump state
`AutonomySettingSpeedbump` now has:
- `ShouldShowForAskUserQuestion { action_id, shown }`
The `action_id` pins the footer to the Ask-User-Question action that triggered it. The `shown` field is set when the footer is attached, matching the broader speedbump pattern and making the attachment state explicit.
## 5. Trigger and one-shot consumption
`AIBlock::handle_complete_output` uses `first_ask_user_question_action_id(output)` to find the first Ask-User-Question action in the completed agent output. It seeds the speedbump when the feature flag is enabled, autonomy is allowed, and the local one-shot setting is still `true`.
Unlike the original design, auto-approve is not excluded. Auto-approve skipped Ask Question actions can seed the same first-use footer.
The local one-shot flag is not consumed at seed time. `sync_ask_user_question_speedbump_footer` returns `true` only after it finds a matching `AskUserQuestionView` and installs the footer. Callers then invoke `mark_ask_user_question_speedbump_as_shown` only on that successful path. If output completion happens before the view exists, the flag remains `true`; `handle_ask_user_question_stream_update` calls the same sync helper after creating/replacing the view and consumes the flag when installation succeeds.
## 6. Dropdown ownership and action flow
`AIBlock` owns `ask_user_question_speedbump_dropdown: Option<ViewHandle<Dropdown<AIBlockAction>>>`. The dropdown is created lazily and reused for the block lifetime.
Dropdown items dispatch `AIBlockAction::SetAskUserQuestionSpeedbumpPermission(permission)`. The handler:
- Resolves the active execution profile for the terminal view.
- Calls `AIExecutionProfilesModel::set_ask_user_question`.
- Emits `ChangedAgentModeAskUserQuestionPermission` with source `Speedbump`.
- Marks the local one-shot setting false idempotently.
- Clears the speedbump state and footer from the current Ask-User-Question view.
- Notifies the block so the footer hides immediately.
Profile model events refresh the dropdown selected index so external settings changes are reflected while the footer exists.
## 7. Footer rendering
The footer is threaded into `AskUserQuestionView` rather than wrapping the child view externally. This keeps the Ask-User-Question card in charge of its own border, radius, and layout.
`AskUserQuestionView` renders the footer as an attached bottom strip:
- Reduced vertical padding for a compressed speedbump height.
- Compact dropdown sizing.
- Bottom radius applied to the footer strip.
- Main card/header radius flattened at the bottom when a footer is present.
- Footer support for collapsed and expanded completed states.
This avoids a double-rounded seam between the card body and the speedbump footer.
## 8. Overlay event routing
The dropdown menu is rendered through WarpUI overlay infrastructure. A covered mouse event previously could be rejected by `BlockListElement` before the rich-content overlay received it, allowing terminal selection or surrounding content to intercept dropdown clicks.
The fix has three parts:
- `BlockListElement` forwards covered mouse events to visible rich-content views before returning.
- `SelectableArea` does not start a selection when a mouse down event is covered at its z-index.
- `Dismiss::prevent_interaction_with_other_elements` consumes mouse events that hit its underlay.
Together these keep dropdown options clickable and make outside-click dismissal reliable.
## 9. Telemetry
The new telemetry event is `ChangedAgentModeAskUserQuestionPermission` with fields:
- `src: AutonomySettingToggleSource`
- `new: AskUserQuestionPermission`
The speedbump path emits the event with `src = Speedbump` whenever the user selects a dropdown option.
## 10. Validation
Local validation:
- `cargo check -p warp`
- `cargo check --all-targets -p warp`
- `cargo nextest run --no-fail-fast -p warp ask_user_question`
- `cargo fmt --all`
- `cargo clippy --workspace --all-targets --all-features --tests -- -D warnings`
- `git --no-pager diff --check`
## 11. Follow-ups
- Add deeper regression coverage for overlay routing if a convenient harness exists for rich-content overlays.
- Consider a shared compact dropdown speedbump component if future autonomy speedbumps need dropdowns.
- Consider an internal reset affordance for local-only onboarding speedbumps to simplify QA.