import type { Job } from "../../../adapters/database/store.js"; import { createIssueSnapshot } from "../../../adapters/gitea/issues.js"; import { marker, planReadyLabel, protocolVersion, } from "../../../core/contracts.js"; import { type PublicationContext, type PublicationOutcome, upsertJobStatus, } from "../status.js"; export async function publishPlan( context: PublicationContext, job: Job, ): Promise { const plan = job.result?.plan; if (!plan) throw new Error("Successful planning job has no plan"); const [issue, comments, repository] = await Promise.all([ context.client.getIssue(job.issueNumber), context.client.getComments(job.issueNumber), context.client.getRepository(), ]); const snapshot = createIssueSnapshot(issue, comments, context.botLogin); const base = await context.client.getBranch(repository.default_branch); if ( snapshot.digest !== plan.issueDigest || base?.commit.id !== plan.baseSha ) { throw new Error( "Issue or default branch changed while planning; the result is stale", ); } const planMarker = { v: protocolVersion, kind: "plan" as const, issue: job.issueNumber, status: "accepted", issueDigest: plan.issueDigest, baseSha: plan.baseSha, planDigest: plan.planDigest, }; const body = `${marker(planMarker)}\n## Accepted implementation plan\n\n${plan.markdown}\n\n\n\n**Summary:** ${plan.summary}\n\nBase: \`${plan.baseSha.slice(0, 12)}\` | Review iterations: ${plan.iterations} | Plan digest: \`${plan.planDigest.slice(0, 12)}\``; const comment = await context.client.upsertMarkedComment( job.issueNumber, context.botLogin, planMarker, body, ); await context.client.addLabelIfPresent(job.issueNumber, planReadyLabel); await upsertJobStatus( context.client, context.botLogin, job, "Agent plan accepted", `The accepted plan was published after ${plan.iterations} review iteration(s).`, ); return { terminal: "succeeded", planCommentId: comment.id }; }