86 lines
9.3 KiB
Markdown
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`.
|