fix(source-control): allow an empty AI-generated PR description in Create PR (#16873)

This commit is contained in:
Neil
2026-08-27 15:36:15 -07:00
committed by GitHub
parent fe71487895
commit 6cdae26e1c
9 changed files with 44 additions and 21 deletions
@@ -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(
@@ -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<CreatePrIntentRunToken, 'startedAt'>) {
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
}
@@ -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
}
-1
View File
@@ -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": {
-1
View File
@@ -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": {
-1
View File
@@ -10770,7 +10770,6 @@
"a4e93c21d7": "現在のブランチ: {{value0}}",
"c7d4e2f801": "ベース ref を変更: {{value0}}",
"f3a1b8c204": "upstream",
"createPrIntentEmptyGeneratedBody": "生成されたレビューの詳細に説明が含まれていませんでした。PR の作成を再試行してください。",
"createPrIntentGenerateDetailsFailed": "レビューの詳細を生成できませんでした。PR の作成を再試行してください。"
},
"SourceControlAgentActionDialog": {
-1
View File
@@ -10791,7 +10791,6 @@
"a4e93c21d7": "현재 브랜치: {{value0}}",
"c7d4e2f801": "베이스 ref 변경: {{value0}}",
"f3a1b8c204": "upstream",
"createPrIntentEmptyGeneratedBody": "생성된 검토 세부 정보에 설명이 포함되지 않았습니다. PR 생성을 다시 시도하세요.",
"createPrIntentGenerateDetailsFailed": "검토 세부 정보를 생성할 수 없습니다. PR 생성을 다시 시도하세요."
},
"SourceControlAgentActionDialog": {
-1
View File
@@ -10826,7 +10826,6 @@
"a4e93c21d7": "当前分支:{{value0}}",
"c7d4e2f801": "更改基引用:{{value0}}",
"f3a1b8c204": "upstream",
"createPrIntentEmptyGeneratedBody": "生成的评审详情未包含描述。请重试创建 PR。",
"createPrIntentGenerateDetailsFailed": "无法生成评审详情。请重试创建 PR。"
},
"SourceControlAgentActionDialog": {
@@ -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