mirror of
https://github.com/github/awesome-copilot.git
synced 2026-10-12 23:04:14 +00:00
Fence review results with required queue tokens, lock concurrent GitHub actions, recover persistence after errors, and reopen feedbacked PRs on new commits. Guard detail request races and add modal focus management and keyboard tabs with regression coverage. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 8045e7e0-dfd7-425a-9131-21ea5ca1553e
132 lines
6.8 KiB
JavaScript
132 lines
6.8 KiB
JavaScript
export const RECOMMENDATION_GUIDE = [
|
|
"`approve` — the change is correct, in scope, compliant with the contribution rules, and ready to merge.",
|
|
"`request-changes` — the idea fits the repository but concrete fixes are required before merge.",
|
|
"`needs-insight` — a maintainer judgement call is needed (policy, duplication, product direction) that a review cannot settle.",
|
|
"`close` — the submission does not belong in this repository and no reasonable revision would change that.",
|
|
].join("\n");
|
|
|
|
/** Shared schema for a single recorded review. Reused directly as the `record_review` input schema. */
|
|
export const REVIEW_FIELDS_SCHEMA = {
|
|
type: "object",
|
|
required: ["number", "queueId", "recommendation", "rationale"],
|
|
properties: {
|
|
number: { type: "integer", description: "Pull request number." },
|
|
queueId: {
|
|
type: "string",
|
|
minLength: 1,
|
|
description: "The current queueId handed out when the review was requested; must match exactly.",
|
|
},
|
|
recommendation: {
|
|
type: "string",
|
|
enum: ["close", "request-changes", "needs-insight", "approve"],
|
|
description: "Which bucket the pull request belongs in.",
|
|
},
|
|
rationale: { type: "string", description: "One sentence explaining the deciding factor, shown on the card." },
|
|
summary: { type: "string", description: "What the pull request actually changes." },
|
|
repoFit: { type: "string", description: "Repository fit and meaningful value for Copilot users." },
|
|
compliance: { type: "string", description: "Deterministic checks: frontmatter, naming, README regeneration, manifests." },
|
|
differentiation: { type: "string", description: "How it differs from existing resources and native model capability." },
|
|
risks: { type: "string", description: "Correctness, security, licensing, or harmful-content concerns." },
|
|
validation: { type: "string", description: "Evidence the contributor tested or validated the change." },
|
|
confidence: { type: "string", enum: ["low", "medium", "high"], description: "Confidence in the recommendation." },
|
|
checkNext: { type: "string", description: "What a maintainer should verify by hand before acting." },
|
|
suggestedComment: { type: "string", description: "A suggested review comment, ready to edit and post." },
|
|
},
|
|
additionalProperties: false,
|
|
};
|
|
|
|
function describeItem(item) {
|
|
const labels = item.labels?.length ? item.labels.map((label) => label.name).join(", ") : "none";
|
|
const checks = item.checkCounts?.total
|
|
? `${item.checkCounts.failure} failing / ${item.checkCounts.pending} pending / ${item.checkCounts.success} passing`
|
|
: "no checks";
|
|
return [
|
|
`- #${item.number} — ${item.title}`,
|
|
` queueId: ${item.queueId}`,
|
|
` author: @${item.author}${item.isDraft ? " (draft)" : ""}`,
|
|
` labels: ${labels}`,
|
|
` diff: +${item.additions}/-${item.deletions} across ${item.changedFiles} files`,
|
|
` checks: ${checks} | review decision: ${item.reviewDecision} | merge state: ${item.mergeStateStatus}`,
|
|
` url: ${item.url}`,
|
|
].join("\n");
|
|
}
|
|
|
|
function sharedRules(repo, guidancePath) {
|
|
return [
|
|
"Work strictly read-only: inspect with `gh` and file reads only. Do not post comments, submit reviews, push commits, or modify the repository.",
|
|
`Review criteria, in priority order, live in \`.github/skills/code-review/SKILL.md\` and \`.github/copilot-instructions.md\` in ${repo}. Read the board's own procedure at ${guidancePath} first.`,
|
|
"For each pull request gather real evidence before deciding:",
|
|
" - `gh pr view <number> -R " + repo + " --comments` for the description and discussion.",
|
|
" - `gh pr diff <number> -R " + repo + "` for the actual change (use `--name-only` first if the diff is large).",
|
|
" - `gh pr checks <number> -R " + repo + "` when checks are failing, to see which ones and why.",
|
|
"Judge the submitted result, not assumptions about the tool that produced it. A title ending in 🤖🤖🤖 is a disclosure, not a defect.",
|
|
].join("\n");
|
|
}
|
|
|
|
function recordingRules(instanceId) {
|
|
return [
|
|
`Record every result by calling \`invoke_canvas_action\` with instanceId \`${instanceId}\`, actionName \`record_review\`, and input \`{ "reviews": [ ... ] }\`.`,
|
|
"Each review object needs `number`, `queueId`, `recommendation`, and `rationale`; fill in `summary`, `repoFit`, `compliance`, `differentiation`, `risks`, `validation`, `confidence`, `checkNext`, and `suggestedComment` whenever you have something real to say.",
|
|
"`suggestedComment` should be the comment you would leave on the pull request — specific, actionable, and written for the author.",
|
|
"You may record in batches as you go. If the canvas is closed, re-open it first with `open_canvas` using canvasId `open-pr-board` and that same instanceId.",
|
|
"",
|
|
"Recommendations:",
|
|
RECOMMENDATION_GUIDE,
|
|
].join("\n");
|
|
}
|
|
|
|
export function buildReviewPrompt({ instanceId, repo, guidancePath, items, decisions }) {
|
|
const calibration = decisions.length
|
|
? [
|
|
"",
|
|
"Recent maintainer decisions on this board — use them to calibrate how strict to be:",
|
|
...decisions
|
|
.slice(0, 12)
|
|
.map((entry) => `- #${entry.number} ${entry.kind}${entry.comment ? `: ${entry.comment.slice(0, 160)}` : ""}`),
|
|
].join("\n")
|
|
: "";
|
|
|
|
return [
|
|
`Review ${items.length} open pull request${items.length === 1 ? "" : "s"} in ${repo} for the Open PR Board canvas.`,
|
|
"",
|
|
sharedRules(repo, guidancePath),
|
|
calibration,
|
|
"",
|
|
"Pull requests to review:",
|
|
items.map(describeItem).join("\n"),
|
|
"",
|
|
recordingRules(instanceId),
|
|
]
|
|
.filter(Boolean)
|
|
.join("\n");
|
|
}
|
|
|
|
export function buildRereviewPrompt({ instanceId, repo, guidancePath, item, guidance, previousReview }) {
|
|
const prior = previousReview
|
|
? [
|
|
"",
|
|
"Previous review:",
|
|
`- recommendation: ${previousReview.recommendation}`,
|
|
`- rationale: ${previousReview.rationale ?? "(none)"}`,
|
|
`- reviewed at: ${previousReview.reviewedAt}`,
|
|
].join("\n")
|
|
: "";
|
|
|
|
return [
|
|
`Re-review pull request #${item.number} in ${repo} for the Open PR Board canvas.`,
|
|
"",
|
|
sharedRules(repo, guidancePath),
|
|
"",
|
|
"Pull request:",
|
|
describeItem(item),
|
|
prior,
|
|
guidance ? `\nMaintainer guidance for this re-review:\n${guidance}` : "",
|
|
"",
|
|
"Start fresh from the evidence; the previous review is context, not a conclusion.",
|
|
"",
|
|
recordingRules(instanceId),
|
|
]
|
|
.filter(Boolean)
|
|
.join("\n");
|
|
}
|