Slice 3: the PR flow

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ben Stull
2026-05-24 12:37:54 -07:00
parent 33d9d7a482
commit a2bf89e90b
15 changed files with 2928 additions and 141 deletions
+73
View File
@@ -197,6 +197,79 @@ export async function resolveThread(slug, branch, threadId) {
return jsonOrThrow(res)
}
// ── Slice 3: the §10 PR flow ─────────────────────────────────────────────
export async function draftPRText(slug, branch) {
const res = await fetch(
`/api/rfcs/${slug}/branches/${encodeURIComponent(branch)}/pr-draft`,
{ method: 'POST' },
)
return jsonOrThrow(res)
}
export async function openPR(slug, branch, { title, description }) {
const res = await fetch(
`/api/rfcs/${slug}/branches/${encodeURIComponent(branch)}/open-pr`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ title, description }),
},
)
return jsonOrThrow(res)
}
export async function getPR(slug, prNumber) {
return jsonOrThrow(await fetch(`/api/rfcs/${slug}/prs/${prNumber}`))
}
export async function advancePRSeen(slug, prNumber, { lastSeenCommitSha, lastSeenMessageId }) {
const res = await fetch(`/api/rfcs/${slug}/prs/${prNumber}/seen`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
last_seen_commit_sha: lastSeenCommitSha,
last_seen_message_id: lastSeenMessageId,
}),
})
return jsonOrThrow(res)
}
export async function postPRReview(slug, prNumber, { text, anchorPayload, quote }) {
const res = await fetch(`/api/rfcs/${slug}/prs/${prNumber}/review`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ text, anchor_payload: anchorPayload || {}, quote: quote || null }),
})
return jsonOrThrow(res)
}
export async function mergePR(slug, prNumber) {
const res = await fetch(`/api/rfcs/${slug}/prs/${prNumber}/merge`, { method: 'POST' })
return jsonOrThrow(res)
}
export async function withdrawPR(slug, prNumber) {
const res = await fetch(`/api/rfcs/${slug}/prs/${prNumber}/withdraw`, { method: 'POST' })
return jsonOrThrow(res)
}
export async function editPRDescription(slug, prNumber, { title, description }) {
const res = await fetch(`/api/rfcs/${slug}/prs/${prNumber}/description`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ title, description }),
})
return jsonOrThrow(res)
}
export async function startResolutionBranch(slug, prNumber) {
const res = await fetch(`/api/rfcs/${slug}/prs/${prNumber}/resolution-branch`, {
method: 'POST',
})
return jsonOrThrow(res)
}
// Stream a chat turn into a per-branch thread. Calls onChunk for each
// text fragment, onChanges when the trailing `changes` event arrives,
// and onDone at the terminal DONE marker. Returns the response headers