Files

86 lines
9.3 KiB
Markdown

# APP-3923: AI-autogenerated commit messages, PR titles, and PR descriptions
## Summary
Pre-populate the code review git dialogs with AI-generated copy so users don't have to write commit messages, PR titles, or PR descriptions by hand. When the commit dialog opens, a draft commit message is generated from the current diff and dropped into the editor. When a PR is created (either standalone "Create PR" or the "Commit and create PR" chain), the PR title and body are generated from the branch's diff and commit history just before `gh pr create` runs.
## Problem
APP-3922 shipped the "Create PR" dialog and the `CommitAndCreatePr` chain, but both relied on the user to write a commit message and both passed `--fill` to `gh pr create`, which just copies the most recent commit subject and body into the PR. That produces mediocre PR titles/descriptions and still requires the user to write a good commit message manually. Writing these is low-value boilerplate users typically want to skip.
## Goals
- Generate a draft commit message automatically when the commit dialog opens so the user only has to review and optionally edit it.
- Generate a PR title and body automatically at PR creation time (both flows: standalone and "Commit and create PR").
- Fail safely: if any generation call fails, the user is told what happened and can recover (type a message manually; retry the PR).
- Keep the user in full control: the generated commit message is always editable; the user can also clear it and type their own.
- Make the commit confirm button's enabled state directly reflect whether a committable message exists — no silent second generation at confirm time.
## Non-goals
- Adding a new feature flag for this capability. `FeatureFlag::GitOperationsInCodeReview` already gates the entire git dialog surface, so autogen is only reachable inside that gate.
- Adding an `AISettings` opt-out or an enterprise / customer-type guard for sending diffs to AI. Both are noted as explicit follow-ups (see `app/src/ai/generate_code_review_content/mod.rs` TODO) and tracked separately.
- A preview/edit UI for the generated PR title and body — they are sent directly to `gh pr create`.
- Regenerate button for commit messages / PR fields.
- Draft PR support (inherited from APP-3922).
- Editing reviewers, labels, or milestones in the dialog (inherited from APP-3922).
## Figma
none provided — this feature is copy-only and reuses the existing dialog layouts from APP-3920 / APP-3922.
## User experience
### Commit message autogeneration (commit dialog)
When the commit dialog opens:
- Placeholder reads `Generating commit message…`.
- Editor buffer is empty.
- Confirm button is disabled (no message, file changes may also still be loading).
- An AI generation request fires immediately in the background using the current diff as input (staged + unstaged, with untracked files included as synthetic diff hunks when `include_unstaged` is true).
On generation success:
- If the editor is still empty (user hasn't typed anything), the generated message is inserted into the editor.
- If the user has already typed a non-empty message, the generated draft is silently discarded — user input is never clobbered.
- Placeholder changes to `Type a commit message` (visible only if the user later clears the buffer).
- Confirm button becomes enabled once file changes have also loaded.
On generation failure (network, server, or empty response):
- Placeholder changes to `Type a commit message`.
- No toast — autogen is best-effort background work, the user can't retry it, and the empty editor plus placeholder already communicate what happened.
- Editor buffer stays empty.
- Confirm button stays disabled until the user types a non-empty message.
### PR title and body autogeneration
Both flows generate PR title and body at confirm time, right before `gh pr create` runs:
**Standalone "Create PR" dialog:**
1. User clicks `Create PR` → dialog goes into loading state (`Creating…`).
2. Compute diff vs main branch and collect commit subjects on the current branch.
3. Generate PR title via AI.
4. Generate PR body via AI.
5. Run `gh pr create --title <generated> --body <generated>`.
6. On success: standard "PR successfully created." toast with `Open PR` link (unchanged from APP-3922).
7. On AI title/body failure: fall back to `gh pr create --fill` so the PR still gets created (with the latest commit's subject/body). On any other step's failure (diff fetch, `gh pr create` itself, etc.): dialog closes, friendly error toast (unchanged from APP-3922 — error mapping is per-call-site log + `user_facing_git_error`).
**"Commit and create PR" chain (commit dialog with `CommitAndCreatePr` intent):**
1. Commit runs.
2. Push runs.
3. Same PR-title / PR-body / `gh pr create` sequence as above.
4. Same success toast.
### Diff input and truncation
- Max diff length sent to AI: 16,000 characters. Beyond that, the diff is truncated on a UTF-8 char boundary with a trailing `... (diff truncated)` marker.
- For commit message generation with `include_unstaged = true`, untracked files are synthesised into diff hunks so the LLM has context for new-file-only commits. Per-untracked-file cap: 4,000 bytes. Binary files are detected from the first 1,024 bytes and skipped.
- For PR generation, the diff is `{base}..origin/{current}` when the remote ref exists, falling back to `{base}..HEAD` otherwise. Commit subjects on the branch are also sent alongside the diff.
### Editor interactions and state rules
1. Confirm is enabled iff there is at least one file change **and** the commit message editor holds a non-empty (trimmed) string.
2. While generation is in flight, the editor is empty, so confirm is implicitly disabled by rule (1); no separate "is autogenerating" flag is exposed.
3. The generated draft never overwrites user input. If the user has typed anything by the time generation resolves, the draft is discarded.
4. Clearing a successful draft after the fact leaves the placeholder `Type a commit message` visible and disables confirm until the user types.
5. There is no confirm-time fallback regeneration for commit messages: once the open-time generation has resolved (success or failure), the user is responsible for the message.
6. A generation failure during PR creation falls back to `gh pr create --fill` so the PR is still created (using the latest commit's subject/body). Only a failure in the PR-creation command itself aborts the flow; in that case, for the `CommitAndCreatePr` chain, the commit and push already succeeded but the PR was not created, and the user can retry via the standalone "Create PR" button.
## Success criteria
1. Opening the commit dialog on a branch with changes kicks off a background AI request within the same frame; the placeholder reads `Generating commit message…` until the request resolves.
2. On generation success with an untouched editor, the generated message appears in the editor within a short time (bounded by AI latency) and the confirm button becomes enabled once file changes are loaded.
3. On generation success with a user-typed message, the generated message is discarded and the user's text is preserved.
4. On generation failure, the placeholder changes to `Type a commit message` (no toast), and confirm stays disabled until the user types.
5. The confirm button is disabled whenever the editor's trimmed content is empty, regardless of whether an auto-generation is still in flight.
6. Clearing a previously-populated AI draft flips the confirm button back to disabled and shows the `Type a commit message` placeholder.
7. Confirming a PR (standalone or via `CommitAndCreatePr`) creates the PR with an AI-generated title and body; the user never types either.
8. A network outage that causes PR title or body generation to fail falls back to `gh pr create --fill`; the PR is still created, using the latest commit's subject/body as title/body.
9. No user-facing AI-related UI appears outside the commit dialog and the two PR-creation confirm paths.
## Validation
- Open the commit dialog on a branch with a non-trivial diff and verify the `Generating commit message…` placeholder, followed by a populated editor with a reasonable draft.
- Type into the editor before the AI responds; verify the typed text is preserved and the draft is discarded.
- Disable networking, open the commit dialog, verify the fallback placeholder (no toast) and that confirm stays disabled until the user types.
- Populate the editor via AI, clear it, verify confirm disables and the `Type a commit message` placeholder re-appears.
- On a pushed branch with no existing PR, click `Create PR` and verify the created PR has a generated title and body (not `--fill`-derived).
- On a branch with pending changes, select `Commit and create PR` in the commit dialog, let it run, and verify commit + push + PR creation, with the PR body and title generated.
- Simulate a failure in PR body generation (e.g. mid-flight network drop) for the `CommitAndCreatePr` flow; verify the PR still gets created via `gh pr create --fill` and the usual success toast appears.
## Open questions
- Should we add a regenerate button for the commit message draft? Currently the user can clear the field and type their own, but they cannot re-trigger AI generation without re-opening the dialog.
- Should PR title and body be editable before `gh pr create` fires? Current design sends them blind.
- AI settings opt-out and enterprise customer-type guard are explicit follow-ups; see `app/src/ai/generate_code_review_content/mod.rs`.