first pass of merging in warp (doesn't build)

This commit is contained in:
Ryan Ward
2026-07-01 16:08:58 -05:00
parent 2f64909469
commit 4770ac06b5
3662 changed files with 414574 additions and 89772 deletions
@@ -0,0 +1,80 @@
# Ask-User-Question Autonomy Speedbump
Linear: [QUALITY-512](https://linear.app/warpdotdev/issue/QUALITY-512/add-ask-user-question-permission-speedbump)
## 1. Summary
When Agent Mode first uses the Ask Question tool on a local client, show a compact inline footer on the Ask-User-Question card that lets the user adjust the active execution profile's Ask Question permission. The footer uses a dropdown with the existing three permission values and links to the AI Autonomy settings page.
## 2. Problem
Users can control how often Agent Mode pauses to ask them questions, but that control is buried in settings. Ask Question is also most noticeable at the moment the agent pauses, so the relevant permission should be surfaced in context the first time the user encounters it. Existing autonomy speedbumps already teach file-read and command execution permissions in context; Ask Question should follow the same pattern.
## 3. Goals
- Surface Ask Question autonomy controls at the moment the tool first appears.
- Let the user update the active execution profile without leaving the conversation.
- Link to the AI Autonomy settings page for users who want the full settings UI.
- Show the nudge only once per local client install/profile state so it does not become noisy.
- Support both normal Ask Question cards and first-use auto-approve skipped Ask Question cases.
- Match the compact visual rhythm of existing autonomy speedbump footers.
## 4. Non-goals
- No new Ask Question permission values.
- No changes to the AI settings page layout.
- No changes to the active Ask-User-Question answer/skip flow.
- No per-conversation or per-repository overrides.
- No global reset UI for speedbumps.
## 5. User experience
### Trigger
The speedbump is seeded when all of the following are true:
- `FeatureFlag::AskUserQuestion` is enabled.
- Agent Mode autonomy is allowed for the workspace.
- The local one-shot setting `should_show_agent_mode_ask_user_question_speedbump` is `true`.
- The completed agent output contains an Ask-User-Question action.
The trigger intentionally includes auto-approve conversations. If Ask Question is skipped because auto-approve is active, the first skipped Ask Question card can still show the footer so the user can discover and adjust the setting.
### One-shot semantics
The one-shot flag is local-only and is not synced through Warp Drive. The flag is consumed once the footer is successfully attached to an Ask-User-Question view. If the agent output is processed before the view exists, the flag remains `true` and is consumed later when the matching view is created and the footer can actually be installed.
The flag is consumed even if the user does not interact with the footer. This keeps the behavior to a single first-use display: if the user notices it and changes the setting, great; if they ignore it, the nudge is still considered displayed and will not reappear on future cards.
### Card placement and layout
- The footer renders as the bottom strip of the Ask-User-Question card.
- The footer is compact, with reduced vertical padding and a smaller dropdown so it feels similar to existing read-file/checkmark speedbumps.
- When the footer is present, the main Ask-User-Question card content does not keep rounded bottom corners; the footer owns the bottom radius so the combined card reads as one attached surface.
- The footer appears for both collapsed and expanded completed cards.
### Footer content
- Left side: short explanatory text and a dropdown.
- Right side: `Manage AI Autonomy permissions` link.
- The settings link opens the AI settings page scoped to the Autonomy section.
### Dropdown behavior
The dropdown options match the settings page order:
- `Never ask``AskUserQuestionPermission::Never`
- `Ask unless auto-approve``AskUserQuestionPermission::AskExceptInAutoApprove`
- `Always ask``AskUserQuestionPermission::AlwaysAsk`
The selected value reflects the active execution profile's current `ask_user_question` permission. Selecting an option immediately updates the active profile, emits telemetry, hides the footer on the current card, and leaves the local one-shot flag consumed.
### Overlay behavior
The dropdown menu renders above surrounding block content. Its options are clickable even when the card is embedded in terminal rich content, and clicking the dropdown underlay dismisses the menu without terminal text selection intercepting the interaction.
## 6. Success criteria
- First normal Ask Question invocation on a local client shows the footer on the resulting card.
- First auto-approve skipped Ask Question invocation also shows the footer on the resulting card.
- The local one-shot flag is not consumed if no matching view exists yet.
- The local one-shot flag is consumed once the footer is attached to the matching view.
- Ignoring the footer does not cause it to reappear on future Ask Question cards.
- Selecting any dropdown option updates the active profile immediately and hides the footer on the current card.
- The dropdown selection stays in sync with external active-profile changes while the footer exists.
- The settings link opens AI settings at the Autonomy section.
- Dropdown options can be clicked and dismissed reliably above terminal/block content.
- Collapsed and expanded cards with the footer render as one attached card with no double-rounded seam.
## 7. Validation
Automated 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`
## 8. Manual QA checklist
- Reset `ShouldShowAgentModeAskUserQuestionSpeedbump` locally to `true`.
- Trigger Ask Question in a normal conversation and confirm the compact footer appears on the card.
- Trigger Ask Question in auto-approve mode and confirm the skipped card can show the same footer on first display.
- Re-trigger Ask Question after ignoring the footer and confirm the footer does not reappear once the flag has been consumed.
- Select each dropdown option and confirm the active profile's setting changes in AI settings.
- Confirm selecting a dropdown option hides the footer.
- Open the dropdown near other rich content and confirm its menu appears above other content, options are clickable, Escape/outside click dismisses it, and terminal selection does not intercept clicks.
- Confirm collapsed and expanded cards have flattened attached corners with the footer present.
@@ -0,0 +1,86 @@
# 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.