Implement GitHub suggestion format instructions (#79)

* implement github suggestion format instructions

add instructions for agents to use github's suggestion format (```suggestion blocks) when providing code suggestions in comments. this enables one-click apply for suggested changes.

updated:
- action/mcp/review.ts: added suggestion format guidance to create_pull_request_review tool description and comment body parameter
- action/mcp/comment.ts: added suggestion format guidance to all comment tools with clarification that suggestions only work on pr line-level review comments
- action/modes.ts: added detailed example in review mode and reminder in address reviews mode

fixes #70

* Address PR review feedback

- Remove suggestion format guidance from report_progress (not applicable)
- De-duplicate description across Comment, EditComment, ReplyToReviewComment
- Drop outer fence in suggestion format example
- Clarify that suggestions only work for self-contained changes
- Remove useless example comment from review tool description

---------

Co-authored-by: pullfrog <team@pullfrog.com>
This commit is contained in:
pullfrog[bot]
2026-01-14 20:41:43 +00:00
committed by pullfrog[bot]
parent 5e291edf05
commit 3b880eb478
6 changed files with 67 additions and 28 deletions
+16 -7
View File
@@ -100417,7 +100417,7 @@ ${dependencyInstallationGuidance}
4. Make the necessary code changes to address the feedback. Work through each review comment systematically.
5. **CRITICAL: Reply to EACH review comment individually.** After fixing each comment, use ${ghPullfrogMcpName}/reply_to_review_comment to reply directly to that comment thread. Keep replies extremely brief (1 sentence max, e.g., "Fixed by renaming to X" or "Added null check").
5. **CRITICAL: Reply to EACH review comment individually.** After fixing each comment, use ${ghPullfrogMcpName}/reply_to_review_comment to reply directly to that comment thread. Keep replies extremely brief (1 sentence max, e.g., "Fixed by renaming to X" or "Added null check"). If suggesting a small, specific, self-contained code change, use GitHub's suggestion format with \`\`\`suggestion blocks.
6. Test your changes to ensure they work correctly.
@@ -100442,7 +100442,15 @@ ${disableProgressComment ? "" : `
- Can you imagine a better approach? If so, explain. Make sure it's strictly better, not just different.
- Are there bugs, edge cases, security issues, or usability issues? Use your imagination.
3. **DRAFT** - For each inline comment, find the line in the diff. Each code line shows: \`| OLD | NEW | TYPE | CODE\`. Use the NEW line number (second column).
3. **DRAFT** - For each inline comment, find the line in the diff. Each code line shows: \`| OLD | NEW | TYPE | CODE\`. Use the NEW line number (second column). When suggesting specific code changes, use GitHub's suggestion format with \`\`\`suggestion blocks to enable one-click apply. Example:
you could simplify this
\`\`\`suggestion
const result = data.map(x => x.value);
\`\`\`
or you could use reduce instead
\`\`\`suggestion
const result = data.reduce((acc, x) => [...acc, x.value], []);
\`\`\`
4. **FILTER COMMENTS** - Do not nitpick! Do not leave compliments that are not actionable. Do not critique the code hygiene or anything stylistic.
@@ -106571,6 +106579,7 @@ async function buildCommentFooter({
}
return buildPullfrogFooter(footerParams);
}
var SUGGESTION_FORMAT_DESCRIPTION = "when suggesting code changes, use GitHub's suggestion format with ```suggestion blocks to enable one-click apply (e.g., 'you could do this\\n```suggestion\\nsuggested code here\\n```'). note: suggestions only work on pull request line-level review comments, not on issue/PR-level comments.";
function buildImplementPlanLink(owner, repo, issueNumber, commentId) {
const apiUrl = process.env.API_URL || "https://pullfrog.com";
return `[Implement plan \u2794](${apiUrl}/trigger/${owner}/${repo}/${issueNumber}?action=implement&comment_id=${commentId})`;
@@ -106582,7 +106591,7 @@ async function addFooter(body, payload, octokit) {
}
var Comment = type({
issueNumber: type.number.describe("the issue number to comment on"),
body: type.string.describe("the comment body content")
body: type.string.describe(`the comment body content. ${SUGGESTION_FORMAT_DESCRIPTION}`)
});
function CreateCommentTool(ctx) {
return tool({
@@ -106608,7 +106617,7 @@ function CreateCommentTool(ctx) {
}
var EditComment = type({
commentId: type.number.describe("the ID of the comment to edit"),
body: type.string.describe("the new comment body content")
body: type.string.describe(`the new comment body content. ${SUGGESTION_FORMAT_DESCRIPTION}`)
});
function EditCommentTool(ctx) {
return tool({
@@ -106829,7 +106838,7 @@ var ReplyToReviewComment = type({
pull_number: type.number.describe("the pull request number"),
comment_id: type.number.describe("the ID of the review comment to reply to"),
body: type.string.describe(
"extremely brief reply (1 sentence max) explaining what was fixed, e.g. 'Fixed by renaming to X' or 'Added null check'"
`extremely brief reply (1 sentence max) explaining what was fixed, e.g. 'Fixed by renaming to X' or 'Added null check'. ${SUGGESTION_FORMAT_DESCRIPTION}`
)
});
function ReplyToReviewCommentTool(ctx) {
@@ -137846,7 +137855,7 @@ var CreatePullRequestReview = type({
"Side of the diff: LEFT (old code, lines starting with -) or RIGHT (new code, lines starting with + or unchanged). Defaults to RIGHT."
).optional(),
body: type.string.describe(
"The comment text for this specific line. For issues appearing multiple times, comment on the first occurrence and reference others."
"The comment text for this specific line. For issues appearing multiple times, comment on the first occurrence and reference others. When providing code suggestions, use GitHub's suggestion format with ```suggestion blocks to enable one-click apply. Only include explanatory text if the suggested code requires clarification."
),
start_line: type.number.describe("Start line for multi-line comments (optional, for commenting on ranges)").optional()
}).array().describe(
@@ -137856,7 +137865,7 @@ var CreatePullRequestReview = type({
function CreatePullRequestReviewTool(ctx) {
return tool({
name: "create_pull_request_review",
description: "Submit a review for an existing pull request. IMPORTANT: 95%+ of feedback should be in 'comments' array with file paths and line numbers. Only use 'body' for a 1-2 sentence summary with urgency and critical callouts.",
description: "Submit a review for an existing pull request. IMPORTANT: 95%+ of feedback should be in 'comments' array with file paths and line numbers. Only use 'body' for a 1-2 sentence summary with urgency and critical callouts. When suggesting code changes in comments, use GitHub's suggestion format (```suggestion blocks) to enable one-click apply.",
parameters: CreatePullRequestReview,
execute: execute(async ({ pull_number, body, commit_id, comments = [] }) => {
ctx.toolState.prNumber = pull_number;
+16 -7
View File
@@ -100417,7 +100417,7 @@ ${dependencyInstallationGuidance}
4. Make the necessary code changes to address the feedback. Work through each review comment systematically.
5. **CRITICAL: Reply to EACH review comment individually.** After fixing each comment, use ${ghPullfrogMcpName}/reply_to_review_comment to reply directly to that comment thread. Keep replies extremely brief (1 sentence max, e.g., "Fixed by renaming to X" or "Added null check").
5. **CRITICAL: Reply to EACH review comment individually.** After fixing each comment, use ${ghPullfrogMcpName}/reply_to_review_comment to reply directly to that comment thread. Keep replies extremely brief (1 sentence max, e.g., "Fixed by renaming to X" or "Added null check"). If suggesting a small, specific, self-contained code change, use GitHub's suggestion format with \`\`\`suggestion blocks.
6. Test your changes to ensure they work correctly.
@@ -100442,7 +100442,15 @@ ${disableProgressComment ? "" : `
- Can you imagine a better approach? If so, explain. Make sure it's strictly better, not just different.
- Are there bugs, edge cases, security issues, or usability issues? Use your imagination.
3. **DRAFT** - For each inline comment, find the line in the diff. Each code line shows: \`| OLD | NEW | TYPE | CODE\`. Use the NEW line number (second column).
3. **DRAFT** - For each inline comment, find the line in the diff. Each code line shows: \`| OLD | NEW | TYPE | CODE\`. Use the NEW line number (second column). When suggesting specific code changes, use GitHub's suggestion format with \`\`\`suggestion blocks to enable one-click apply. Example:
you could simplify this
\`\`\`suggestion
const result = data.map(x => x.value);
\`\`\`
or you could use reduce instead
\`\`\`suggestion
const result = data.reduce((acc, x) => [...acc, x.value], []);
\`\`\`
4. **FILTER COMMENTS** - Do not nitpick! Do not leave compliments that are not actionable. Do not critique the code hygiene or anything stylistic.
@@ -106571,6 +106579,7 @@ async function buildCommentFooter({
}
return buildPullfrogFooter(footerParams);
}
var SUGGESTION_FORMAT_DESCRIPTION = "when suggesting code changes, use GitHub's suggestion format with ```suggestion blocks to enable one-click apply (e.g., 'you could do this\\n```suggestion\\nsuggested code here\\n```'). note: suggestions only work on pull request line-level review comments, not on issue/PR-level comments.";
function buildImplementPlanLink(owner, repo, issueNumber, commentId) {
const apiUrl = process.env.API_URL || "https://pullfrog.com";
return `[Implement plan \u2794](${apiUrl}/trigger/${owner}/${repo}/${issueNumber}?action=implement&comment_id=${commentId})`;
@@ -106582,7 +106591,7 @@ async function addFooter(body, payload, octokit) {
}
var Comment = type({
issueNumber: type.number.describe("the issue number to comment on"),
body: type.string.describe("the comment body content")
body: type.string.describe(`the comment body content. ${SUGGESTION_FORMAT_DESCRIPTION}`)
});
function CreateCommentTool(ctx) {
return tool({
@@ -106608,7 +106617,7 @@ function CreateCommentTool(ctx) {
}
var EditComment = type({
commentId: type.number.describe("the ID of the comment to edit"),
body: type.string.describe("the new comment body content")
body: type.string.describe(`the new comment body content. ${SUGGESTION_FORMAT_DESCRIPTION}`)
});
function EditCommentTool(ctx) {
return tool({
@@ -106829,7 +106838,7 @@ var ReplyToReviewComment = type({
pull_number: type.number.describe("the pull request number"),
comment_id: type.number.describe("the ID of the review comment to reply to"),
body: type.string.describe(
"extremely brief reply (1 sentence max) explaining what was fixed, e.g. 'Fixed by renaming to X' or 'Added null check'"
`extremely brief reply (1 sentence max) explaining what was fixed, e.g. 'Fixed by renaming to X' or 'Added null check'. ${SUGGESTION_FORMAT_DESCRIPTION}`
)
});
function ReplyToReviewCommentTool(ctx) {
@@ -137846,7 +137855,7 @@ var CreatePullRequestReview = type({
"Side of the diff: LEFT (old code, lines starting with -) or RIGHT (new code, lines starting with + or unchanged). Defaults to RIGHT."
).optional(),
body: type.string.describe(
"The comment text for this specific line. For issues appearing multiple times, comment on the first occurrence and reference others."
"The comment text for this specific line. For issues appearing multiple times, comment on the first occurrence and reference others. When providing code suggestions, use GitHub's suggestion format with ```suggestion blocks to enable one-click apply. Only include explanatory text if the suggested code requires clarification."
),
start_line: type.number.describe("Start line for multi-line comments (optional, for commenting on ranges)").optional()
}).array().describe(
@@ -137856,7 +137865,7 @@ var CreatePullRequestReview = type({
function CreatePullRequestReviewTool(ctx) {
return tool({
name: "create_pull_request_review",
description: "Submit a review for an existing pull request. IMPORTANT: 95%+ of feedback should be in 'comments' array with file paths and line numbers. Only use 'body' for a 1-2 sentence summary with urgency and critical callouts.",
description: "Submit a review for an existing pull request. IMPORTANT: 95%+ of feedback should be in 'comments' array with file paths and line numbers. Only use 'body' for a 1-2 sentence summary with urgency and critical callouts. When suggesting code changes in comments, use GitHub's suggestion format (```suggestion blocks) to enable one-click apply.",
parameters: CreatePullRequestReview,
execute: execute(async ({ pull_number, body, commit_id, comments = [] }) => {
ctx.toolState.prNumber = pull_number;
+6 -3
View File
@@ -77,6 +77,9 @@ async function buildCommentFooter({
return buildPullfrogFooter(footerParams);
}
const SUGGESTION_FORMAT_DESCRIPTION =
"when suggesting code changes, use GitHub's suggestion format with ```suggestion blocks to enable one-click apply (e.g., 'you could do this\\n```suggestion\\nsuggested code here\\n```'). note: suggestions only work on pull request line-level review comments, not on issue/PR-level comments.";
function buildImplementPlanLink(
owner: string,
repo: string,
@@ -99,7 +102,7 @@ async function addFooter(
export const Comment = type({
issueNumber: type.number.describe("the issue number to comment on"),
body: type.string.describe("the comment body content"),
body: type.string.describe(`the comment body content. ${SUGGESTION_FORMAT_DESCRIPTION}`),
});
export function CreateCommentTool(ctx: ToolContext) {
@@ -130,7 +133,7 @@ export function CreateCommentTool(ctx: ToolContext) {
export const EditComment = type({
commentId: type.number.describe("the ID of the comment to edit"),
body: type.string.describe("the new comment body content"),
body: type.string.describe(`the new comment body content. ${SUGGESTION_FORMAT_DESCRIPTION}`),
});
export function EditCommentTool(ctx: ToolContext) {
@@ -472,7 +475,7 @@ export const ReplyToReviewComment = type({
pull_number: type.number.describe("the pull request number"),
comment_id: type.number.describe("the ID of the review comment to reply to"),
body: type.string.describe(
"extremely brief reply (1 sentence max) explaining what was fixed, e.g. 'Fixed by renaming to X' or 'Added null check'"
`extremely brief reply (1 sentence max) explaining what was fixed, e.g. 'Fixed by renaming to X' or 'Added null check'. ${SUGGESTION_FORMAT_DESCRIPTION}`
),
});
+3 -2
View File
@@ -29,7 +29,7 @@ export const CreatePullRequestReview = type({
)
.optional(),
body: type.string.describe(
"The comment text for this specific line. For issues appearing multiple times, comment on the first occurrence and reference others."
"The comment text for this specific line. For issues appearing multiple times, comment on the first occurrence and reference others. When providing code suggestions, use GitHub's suggestion format with ```suggestion blocks to enable one-click apply. Only include explanatory text if the suggested code requires clarification."
),
start_line: type.number
.describe("Start line for multi-line comments (optional, for commenting on ranges)")
@@ -48,7 +48,8 @@ export function CreatePullRequestReviewTool(ctx: ToolContext) {
description:
"Submit a review for an existing pull request. " +
"IMPORTANT: 95%+ of feedback should be in 'comments' array with file paths and line numbers. " +
"Only use 'body' for a 1-2 sentence summary with urgency and critical callouts.",
"Only use 'body' for a 1-2 sentence summary with urgency and critical callouts. " +
"When suggesting code changes in comments, use GitHub's suggestion format (```suggestion blocks) to enable one-click apply.",
parameters: CreatePullRequestReview,
execute: execute(async ({ pull_number, body, commit_id, comments = [] }) => {
// set PR context
+10 -2
View File
@@ -89,7 +89,7 @@ ${dependencyInstallationGuidance}
4. Make the necessary code changes to address the feedback. Work through each review comment systematically.
5. **CRITICAL: Reply to EACH review comment individually.** After fixing each comment, use ${ghPullfrogMcpName}/reply_to_review_comment to reply directly to that comment thread. Keep replies extremely brief (1 sentence max, e.g., "Fixed by renaming to X" or "Added null check").
5. **CRITICAL: Reply to EACH review comment individually.** After fixing each comment, use ${ghPullfrogMcpName}/reply_to_review_comment to reply directly to that comment thread. Keep replies extremely brief (1 sentence max, e.g., "Fixed by renaming to X" or "Added null check"). If suggesting a small, specific, self-contained code change, use GitHub's suggestion format with \`\`\`suggestion blocks.
6. Test your changes to ensure they work correctly.
@@ -119,7 +119,15 @@ ${
- Can you imagine a better approach? If so, explain. Make sure it's strictly better, not just different.
- Are there bugs, edge cases, security issues, or usability issues? Use your imagination.
3. **DRAFT** - For each inline comment, find the line in the diff. Each code line shows: \`| OLD | NEW | TYPE | CODE\`. Use the NEW line number (second column).
3. **DRAFT** - For each inline comment, find the line in the diff. Each code line shows: \`| OLD | NEW | TYPE | CODE\`. Use the NEW line number (second column). When suggesting specific code changes, use GitHub's suggestion format with \`\`\`suggestion blocks to enable one-click apply. Example:
you could simplify this
\`\`\`suggestion
const result = data.map(x => x.value);
\`\`\`
or you could use reduce instead
\`\`\`suggestion
const result = data.reduce((acc, x) => [...acc, x.value], []);
\`\`\`
4. **FILTER COMMENTS** - Do not nitpick! Do not leave compliments that are not actionable. Do not critique the code hygiene or anything stylistic.
+16 -7
View File
@@ -100417,7 +100417,7 @@ ${dependencyInstallationGuidance}
4. Make the necessary code changes to address the feedback. Work through each review comment systematically.
5. **CRITICAL: Reply to EACH review comment individually.** After fixing each comment, use ${ghPullfrogMcpName}/reply_to_review_comment to reply directly to that comment thread. Keep replies extremely brief (1 sentence max, e.g., "Fixed by renaming to X" or "Added null check").
5. **CRITICAL: Reply to EACH review comment individually.** After fixing each comment, use ${ghPullfrogMcpName}/reply_to_review_comment to reply directly to that comment thread. Keep replies extremely brief (1 sentence max, e.g., "Fixed by renaming to X" or "Added null check"). If suggesting a small, specific, self-contained code change, use GitHub's suggestion format with \`\`\`suggestion blocks.
6. Test your changes to ensure they work correctly.
@@ -100442,7 +100442,15 @@ ${disableProgressComment ? "" : `
- Can you imagine a better approach? If so, explain. Make sure it's strictly better, not just different.
- Are there bugs, edge cases, security issues, or usability issues? Use your imagination.
3. **DRAFT** - For each inline comment, find the line in the diff. Each code line shows: \`| OLD | NEW | TYPE | CODE\`. Use the NEW line number (second column).
3. **DRAFT** - For each inline comment, find the line in the diff. Each code line shows: \`| OLD | NEW | TYPE | CODE\`. Use the NEW line number (second column). When suggesting specific code changes, use GitHub's suggestion format with \`\`\`suggestion blocks to enable one-click apply. Example:
you could simplify this
\`\`\`suggestion
const result = data.map(x => x.value);
\`\`\`
or you could use reduce instead
\`\`\`suggestion
const result = data.reduce((acc, x) => [...acc, x.value], []);
\`\`\`
4. **FILTER COMMENTS** - Do not nitpick! Do not leave compliments that are not actionable. Do not critique the code hygiene or anything stylistic.
@@ -106571,6 +106579,7 @@ async function buildCommentFooter({
}
return buildPullfrogFooter(footerParams);
}
var SUGGESTION_FORMAT_DESCRIPTION = "when suggesting code changes, use GitHub's suggestion format with ```suggestion blocks to enable one-click apply (e.g., 'you could do this\\n```suggestion\\nsuggested code here\\n```'). note: suggestions only work on pull request line-level review comments, not on issue/PR-level comments.";
function buildImplementPlanLink(owner, repo, issueNumber, commentId) {
const apiUrl = process.env.API_URL || "https://pullfrog.com";
return `[Implement plan \u2794](${apiUrl}/trigger/${owner}/${repo}/${issueNumber}?action=implement&comment_id=${commentId})`;
@@ -106582,7 +106591,7 @@ async function addFooter(body, payload, octokit) {
}
var Comment = type({
issueNumber: type.number.describe("the issue number to comment on"),
body: type.string.describe("the comment body content")
body: type.string.describe(`the comment body content. ${SUGGESTION_FORMAT_DESCRIPTION}`)
});
function CreateCommentTool(ctx) {
return tool({
@@ -106608,7 +106617,7 @@ function CreateCommentTool(ctx) {
}
var EditComment = type({
commentId: type.number.describe("the ID of the comment to edit"),
body: type.string.describe("the new comment body content")
body: type.string.describe(`the new comment body content. ${SUGGESTION_FORMAT_DESCRIPTION}`)
});
function EditCommentTool(ctx) {
return tool({
@@ -106829,7 +106838,7 @@ var ReplyToReviewComment = type({
pull_number: type.number.describe("the pull request number"),
comment_id: type.number.describe("the ID of the review comment to reply to"),
body: type.string.describe(
"extremely brief reply (1 sentence max) explaining what was fixed, e.g. 'Fixed by renaming to X' or 'Added null check'"
`extremely brief reply (1 sentence max) explaining what was fixed, e.g. 'Fixed by renaming to X' or 'Added null check'. ${SUGGESTION_FORMAT_DESCRIPTION}`
)
});
function ReplyToReviewCommentTool(ctx) {
@@ -137846,7 +137855,7 @@ var CreatePullRequestReview = type({
"Side of the diff: LEFT (old code, lines starting with -) or RIGHT (new code, lines starting with + or unchanged). Defaults to RIGHT."
).optional(),
body: type.string.describe(
"The comment text for this specific line. For issues appearing multiple times, comment on the first occurrence and reference others."
"The comment text for this specific line. For issues appearing multiple times, comment on the first occurrence and reference others. When providing code suggestions, use GitHub's suggestion format with ```suggestion blocks to enable one-click apply. Only include explanatory text if the suggested code requires clarification."
),
start_line: type.number.describe("Start line for multi-line comments (optional, for commenting on ranges)").optional()
}).array().describe(
@@ -137856,7 +137865,7 @@ var CreatePullRequestReview = type({
function CreatePullRequestReviewTool(ctx) {
return tool({
name: "create_pull_request_review",
description: "Submit a review for an existing pull request. IMPORTANT: 95%+ of feedback should be in 'comments' array with file paths and line numbers. Only use 'body' for a 1-2 sentence summary with urgency and critical callouts.",
description: "Submit a review for an existing pull request. IMPORTANT: 95%+ of feedback should be in 'comments' array with file paths and line numbers. Only use 'body' for a 1-2 sentence summary with urgency and critical callouts. When suggesting code changes in comments, use GitHub's suggestion format (```suggestion blocks) to enable one-click apply.",
parameters: CreatePullRequestReview,
execute: execute(async ({ pull_number, body, commit_id, comments = [] }) => {
ctx.toolState.prNumber = pull_number;