diff --git a/src/renderer/src/components/right-sidebar/source-control-create-pr-intent-flow.test.ts b/src/renderer/src/components/right-sidebar/source-control-create-pr-intent-flow.test.ts index 3072fd76642..f89236426cb 100644 --- a/src/renderer/src/components/right-sidebar/source-control-create-pr-intent-flow.test.ts +++ b/src/renderer/src/components/right-sidebar/source-control-create-pr-intent-flow.test.ts @@ -342,12 +342,6 @@ describe('source-control Create PR intent flow helpers', () => { error: 'Agent timed out.' }) ).toEqual({ ok: false, error: 'Agent timed out.' }) - expect( - resolveCreatePrIntentGeneratedReviewFields(current, { - success: true, - fields: { ...current, title: 'Generated title', body: ' ' } - }) - ).toEqual({ ok: false, error: null }) expect( resolveCreatePrIntentGeneratedReviewFields(current, { success: true, @@ -369,6 +363,33 @@ describe('source-control Create PR intent flow helpers', () => { }) }) + it('accepts generated review fields with an empty description', () => { + expect( + resolveCreatePrIntentGeneratedReviewFields( + { base: 'main', title: 'Feature branch', body: '', draft: false }, + { + success: true, + fields: { base: 'main', title: 'chore: add new app config', body: '', draft: false } + } + ) + ).toEqual({ + ok: true, + fields: { base: 'main', title: 'chore: add new app config', body: '', draft: false } + }) + }) + + it('falls back to the current title when the generated title is blank and the body is empty', () => { + expect( + resolveCreatePrIntentGeneratedReviewFields( + { base: 'main', title: 'Feature branch', body: '', draft: false }, + { success: true, fields: { base: 'main', title: ' ', body: ' ', draft: true } } + ) + ).toEqual({ + ok: true, + fields: { base: 'main', title: 'Feature branch', body: ' ', draft: true } + }) + }) + it('surfaces the commit failure summary in the Create PR intent notice', () => { expect( getCreatePrIntentCommitFailureNoticeMessage( diff --git a/src/renderer/src/components/right-sidebar/source-control/review/create-pr-intent-flow.ts b/src/renderer/src/components/right-sidebar/source-control/review/create-pr-intent-flow.ts index 669f7b3142a..d72d6dcc86e 100644 --- a/src/renderer/src/components/right-sidebar/source-control/review/create-pr-intent-flow.ts +++ b/src/renderer/src/components/right-sidebar/source-control/review/create-pr-intent-flow.ts @@ -53,7 +53,7 @@ type CreatePrIntentReviewGeneration = export type CreatePrIntentGeneratedReviewFields = | { ok: true; fields: CreatePrIntentReviewFields } - | { ok: false; error: string | null } + | { ok: false; error: string } export function createCreatePrIntentRunToken(input: Omit) { return { ...input, startedAt: Date.now() } @@ -208,15 +208,13 @@ export function resolveCreatePrIntentGeneratedReviewFields( if (!generated.success) { return { ok: false, error: generated.error } } - if (!generated.fields.body.trim()) { - return { ok: false, error: null } - } return { ok: true, fields: { // Why: intent auto-submits, so generated details must not retarget the review without confirmation. base: current.base, title: generated.fields.title.trim() || current.title, + // Why: a description is optional everywhere else (composer, GitHub/GitLab), so an intentionally empty generated body is a valid result, not a failure. body: generated.fields.body, draft: generated.fields.draft } diff --git a/src/renderer/src/components/right-sidebar/source-control/review/use-create-pr-intent-review.ts b/src/renderer/src/components/right-sidebar/source-control/review/use-create-pr-intent-review.ts index e6b9b2f6b38..373148e4fc2 100644 --- a/src/renderer/src/components/right-sidebar/source-control/review/use-create-pr-intent-review.ts +++ b/src/renderer/src/components/right-sidebar/source-control/review/use-create-pr-intent-review.ts @@ -132,12 +132,7 @@ export function useSourceControlCreatePrIntentReview({ if (!resolved.ok) { setCreatePrIntentNoticeForWorktree(token.worktreeId, { tone: 'destructive', - message: - resolved.error ?? - translate( - 'auto.components.right.sidebar.SourceControl.createPrIntentEmptyGeneratedBody', - 'Generated review details did not include a description. Retry Create PR.' - ) + message: resolved.error }) return false } diff --git a/src/renderer/src/i18n/locales/en.json b/src/renderer/src/i18n/locales/en.json index 3cfec9b3695..599c1a5d6d0 100644 --- a/src/renderer/src/i18n/locales/en.json +++ b/src/renderer/src/i18n/locales/en.json @@ -12000,7 +12000,6 @@ "a4e93c21d7": "Current branch: {{value0}}", "c7d4e2f801": "Change base ref: {{value0}}", "f3a1b8c204": "upstream", - "createPrIntentEmptyGeneratedBody": "Generated review details did not include a description. Retry Create PR.", "createPrIntentGenerateDetailsFailed": "Could not generate review details. Retry Create PR." }, "SourceControlAgentActionDialog": { diff --git a/src/renderer/src/i18n/locales/es.json b/src/renderer/src/i18n/locales/es.json index 5142116a66b..8b014a386da 100644 --- a/src/renderer/src/i18n/locales/es.json +++ b/src/renderer/src/i18n/locales/es.json @@ -10779,7 +10779,6 @@ "a4e93c21d7": "Rama actual: {{value0}}", "c7d4e2f801": "Cambiar ref base: {{value0}}", "f3a1b8c204": "upstream", - "createPrIntentEmptyGeneratedBody": "Los detalles de revisión generados no incluyeron una descripción. Reintentar Crear PR.", "createPrIntentGenerateDetailsFailed": "No se pudieron generar los detalles de revisión. Reintentar Crear PR." }, "SourceControlAgentActionDialog": { diff --git a/src/renderer/src/i18n/locales/ja.json b/src/renderer/src/i18n/locales/ja.json index 1c72acfa367..0e5e5fd0e9d 100644 --- a/src/renderer/src/i18n/locales/ja.json +++ b/src/renderer/src/i18n/locales/ja.json @@ -10770,7 +10770,6 @@ "a4e93c21d7": "現在のブランチ: {{value0}}", "c7d4e2f801": "ベース ref を変更: {{value0}}", "f3a1b8c204": "upstream", - "createPrIntentEmptyGeneratedBody": "生成されたレビューの詳細に説明が含まれていませんでした。PR の作成を再試行してください。", "createPrIntentGenerateDetailsFailed": "レビューの詳細を生成できませんでした。PR の作成を再試行してください。" }, "SourceControlAgentActionDialog": { diff --git a/src/renderer/src/i18n/locales/ko.json b/src/renderer/src/i18n/locales/ko.json index 5b062ebeeee..36700af527d 100644 --- a/src/renderer/src/i18n/locales/ko.json +++ b/src/renderer/src/i18n/locales/ko.json @@ -10791,7 +10791,6 @@ "a4e93c21d7": "현재 브랜치: {{value0}}", "c7d4e2f801": "베이스 ref 변경: {{value0}}", "f3a1b8c204": "upstream", - "createPrIntentEmptyGeneratedBody": "생성된 검토 세부 정보에 설명이 포함되지 않았습니다. PR 생성을 다시 시도하세요.", "createPrIntentGenerateDetailsFailed": "검토 세부 정보를 생성할 수 없습니다. PR 생성을 다시 시도하세요." }, "SourceControlAgentActionDialog": { diff --git a/src/renderer/src/i18n/locales/zh.json b/src/renderer/src/i18n/locales/zh.json index 5a680d43a8b..099a734060a 100644 --- a/src/renderer/src/i18n/locales/zh.json +++ b/src/renderer/src/i18n/locales/zh.json @@ -10826,7 +10826,6 @@ "a4e93c21d7": "当前分支:{{value0}}", "c7d4e2f801": "更改基引用:{{value0}}", "f3a1b8c204": "upstream", - "createPrIntentEmptyGeneratedBody": "生成的评审详情未包含描述。请重试创建 PR。", "createPrIntentGenerateDetailsFailed": "无法生成评审详情。请重试创建 PR。" }, "SourceControlAgentActionDialog": { diff --git a/src/shared/pull-request-generation.test.ts b/src/shared/pull-request-generation.test.ts index be18305e3f0..0bb21502bec 100644 --- a/src/shared/pull-request-generation.test.ts +++ b/src/shared/pull-request-generation.test.ts @@ -173,6 +173,20 @@ describe('parseGeneratedPullRequestFields', () => { }) }) + it('keeps an explicitly empty body instead of falling back', () => { + const fields = parseGeneratedPullRequestFields( + '{"base":"main","title":"chore: add new app config","body":"","draft":false}', + context + ) + + expect(fields).toEqual({ + base: 'main', + title: 'chore: add new app config', + body: '', + draft: false + }) + }) + it('rejects excessive nesting before JSON.parse', () => { const parseSpy = vi.spyOn(JSON, 'parse') const depth = GENERATED_PULL_REQUEST_JSON_STRUCTURE_LIMITS.nestingDepth + 1