import { requirementKinds, type BetaPlan } from './beta-plan.js'; export const betaDraftKey = 'electric-cherry:beta-draft:v1'; export interface BetaDraft { version: 1; savedAt: string; step: number; picks: Array<{ scriptId: number | null; versionId: number | null }>; servers: string[]; testPlan: BetaPlan; label?: string; } /** Validate draft structure, preserving incomplete numeric fields for correction. */ export function readBetaDraft(raw: string | null): BetaDraft | null { if (!raw) return null; try { const d = JSON.parse(raw); if (d?.version !== 1 || !Array.isArray(d.picks) || !d.picks.length || d.picks.length > 100 || !d.picks.every((p: BetaDraft['picks'][number]) => p && [p.scriptId, p.versionId].every(v => v === null || Number.isSafeInteger(v) && v! > 0)) || !Array.isArray(d.servers) || !d.servers.every((s: unknown) => typeof s === 'string') || d.testPlan?.version !== 1 || !Array.isArray(d.testPlan.requirements) || d.testPlan.requirements.length > 30 || !d.testPlan.requirements.every((r: BetaPlan['requirements'][number]) => r && requirementKinds.includes(r.kind) && typeof r.id === 'string' && /^[a-zA-Z0-9_-]{1,64}$/.test(r.id) && typeof r.label === 'string')) return null; return { ...d, step: Math.max(0, Math.min(3, Number(d.step) || 0)) }; } catch { return null; } } export function compatibleBetaServers(selected: Iterable, candidates: readonly string[]): { kept: Set; removed: string[] } { const allowed = new Set(candidates), names = [...selected]; return { kept: new Set(names.filter(name => allowed.has(name))), removed: names.filter(name => !allowed.has(name)) }; }