/** Shallow diff between two plain objects for blueprint comparison. */ export function blueprintDiff( base: Record, current: Record ): { key: string; kind: 'added' | 'removed' | 'changed'; from?: unknown; to?: unknown }[] { const keys = new Set([...Object.keys(base), ...Object.keys(current)]); const out: { key: string; kind: 'added' | 'removed' | 'changed'; from?: unknown; to?: unknown }[] = []; for (const key of keys) { const a = base[key]; const b = current[key]; const hasA = key in base; const hasB = key in current; if (!hasA && hasB) { out.push({ key, kind: 'added', to: b }); } else if (hasA && !hasB) { out.push({ key, kind: 'removed', from: a }); } else if (JSON.stringify(a) !== JSON.stringify(b)) { out.push({ key, kind: 'changed', from: a, to: b }); } } return out.sort((x, y) => x.key.localeCompare(y.key)); } /** Build partial forge request from a stored build record. */ export function buildRequestFromRecord( record: { worker_name: string; server_url: string; wallet: string; threads: number; pool_host: string; pool_port: number; pool_tls: boolean; pool_pass: string; }, defaults: Record ): Record { return { ...defaults, worker_name: record.worker_name, server_url: record.server_url, wallet: record.wallet, threads: record.threads, pool_host: record.pool_host, pool_port: record.pool_port, pool_tls: record.pool_tls, pool_pass: record.pool_pass, }; }