import { assertCoordinatorArtifactPath, assertCoordinatorWorkdir, buildCoordinatorMcpConfig, type CoordinatorMcpConfig, type CoordinatorMutationClass, requireCoordinatorMutation, } from "./policy"; export const COORDINATOR_MUTATION_CLASSES = ["sessions", "questions", "reports"] as const; export type { CoordinatorMutationClass }; export interface CoordinatorSafetyConfig { allowedRoots: string[]; artifactMaxBytes: number; enabledMutationClasses: Set; repo?: string; profile?: string; } export interface CoordinatorSafetyPolicy { config: CoordinatorSafetyConfig; resolveWorkdir(input: unknown): Promise; resolveArtifactPath(input: unknown): Promise; assertMutationAllowed( mutationClass: CoordinatorMutationClass, args: Record, ): { ok: true } | CoordinatorFailure; } export interface CoordinatorFailure { ok: false; reason: string; [key: string]: unknown; } function toSafetyConfig(config: CoordinatorMcpConfig): CoordinatorSafetyConfig { return { allowedRoots: config.allowedRoots, artifactMaxBytes: config.artifactByteCap, enabledMutationClasses: config.mutationClasses, repo: config.namespace.repo ?? undefined, profile: config.namespace.profile ?? undefined, }; } function toFailure(error: unknown): CoordinatorFailure { const message = error instanceof Error ? error.message : String(error); const [rawReason, detail] = message.split(":", 2); const reason = rawReason.replace(/^coordinator_/, ""); return detail === undefined ? { ok: false, reason } : { ok: false, reason, detail }; } export async function createCoordinatorSafetyPolicy( options: { env?: NodeJS.ProcessEnv } = {}, ): Promise { const canonicalConfig = buildCoordinatorMcpConfig(options.env ?? process.env); const config = toSafetyConfig(canonicalConfig); return { config, resolveWorkdir(input: unknown): Promise { return assertCoordinatorWorkdir(canonicalConfig, input); }, async resolveArtifactPath(input: unknown): Promise { return (await assertCoordinatorArtifactPath(canonicalConfig, input)).path; }, assertMutationAllowed( mutationClass: CoordinatorMutationClass, args: Record, ): { ok: true } | CoordinatorFailure { try { requireCoordinatorMutation(canonicalConfig, mutationClass, args); return { ok: true }; } catch (error) { return toFailure(error); } }, }; }