39 lines · 1.3 KB
import { forbidden } from "../../errors";

export const UNCONFIRMED_APPROVAL = "_Approval requested by an agent without human confirmation; not counted._";

type ReviewEvent = "approve" | "request_changes" | "comment";

/**
 * The stored review state for an agent's review. An approval only counts (toward branch protection and
 * merge automation) when a human confirmed it; otherwise it is kept as a comment.
 */
export function agentReview(
  event: ReviewEvent,
  humanConfirmed: boolean,
  body: string,
): {
  state: "approved" | "changes_requested" | "commented";
  text: string;
  unconfirmed: boolean;
} {
  if (event === "approve" && humanConfirmed) return { state: "approved", text: body.trim(), unconfirmed: false };
  if (event === "approve")
    return {
      state: "commented",
      text: `${UNCONFIRMED_APPROVAL}\n\n${body}`.trim(),
      unconfirmed: true,
    };
  return {
    state: event === "request_changes" ? "changes_requested" : "commented",
    text: body.trim(),
    unconfirmed: false,
  };
}

/** Merging is irreversible and PR content may steer the agent, so it needs a client that can ask a human. */
export function requireHumanForMerge(humanAvailable: boolean): void {
  if (!humanAvailable)
    throw forbidden("Merging needs a client that can ask a human to confirm; merge from the web instead");
}