Add Sentry Triage canvas extension (#2802)

An on-call error-triage canvas for GitHub Copilot: scans live Sentry
issues, groups them by urgency, and hands issues off for tracking or a
fix PR. Registers a reusable canvas extension under extensions/ with a
matching plugins/sentry-triage manifest.

The extension runs a loopback HTTP/SSE server per canvas instance
(host-allow-listed, per-instance capability token never broadcast over
SSE), renders the triage board server- and client-side, and drives
model turns over a single shared Copilot session serialized so scan and
work turns can't interleave. Work state is prototype-pollution-guarded
against agent-controlled tracking keys, and sendAndWait timeouts are
handled without duplicating external side effects.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Liz Tom
2026-08-26 10:04:22 +10:00
committed by GitHub
co-authored by Copilot App
parent 7c36d87f82
commit b6da04c241
22 changed files with 7267 additions and 0 deletions
@@ -0,0 +1,29 @@
import { Card } from './card.mjs'
import { escapeHtml } from '../escape.mjs'
const CATEGORY_DESCRIPTIONS = {
'regressions': 'Issues that previously existed, were resolved, and have resurfaced — likely tied to a recent release.',
'escalating': 'Issues Sentry flagged as escalating, plus older high-impact issues affecting many users or generating many events.',
'new-critical': 'Brand new issues that have already hit multiple users within hours of first appearing.'
}
export function Category({ id, name, issues, plainEnglishView, availableModels = [] }) {
if (!issues.length) return ''
const description = CATEGORY_DESCRIPTIONS[id] || ''
const safeId = escapeHtml(id)
return `<section class="category" data-category="${safeId}">
<div class="category-header">
<h2>${escapeHtml(name)} <span class="badge">${issues.length}</span></h2>
<label class="category-select-all">
<input type="checkbox" class="category-check" data-category="${safeId}" />
Select all
</label>
${description ? `<p class="category-description">${description}</p>` : ''}
</div>
<div class="card-list">
${issues.map((issue) => Card({ ...issue, plainEnglishView, availableModels })).join('')}
</div>
</section>`
}