// Plain-text views of broker results. Every function takes what the broker // returned and keeps its order: the broker sorts, this file never re-sorts. const one = (s, max = 160) => { const flat = String(s ?? "").replace(/\s+/g, " ").trim(); return flat.length > max ? `${flat.slice(0, max - 1)}…` : flat; }; export const shortId = (id) => String(id).slice(0, 8); export function optionsLine(d) { return d.options.map((o) => `${o.key} = ${one(o.text, 80)}`).join("; "); } // What approving means, when the decision carries authorization context. export function authorizationLines(d) { const a = d.authorization; if (!a) return []; const lines = [`action: ${a.action}${a.target ? ` on ${a.target}` : ""}`]; lines.push(`choosing "${a.approvalChoice}" authorizes it; any other choice declines`); return lines; } export function formatInbox(list) { if (list.length === 0) return "inbox: empty\n"; const out = [`inbox: ${list.length} open decision(s)`]; for (const d of list) { const flags = [d.class, d.blocking ? "blocking" : null].filter(Boolean).join(", "); out.push("", `${shortId(d.id)} ${d.action} (${flags}) raised ${d.at} by ${d.raised_by_role}`); out.push(` ${one(d.question, 400)}`); out.push(` options: ${optionsLine(d)} (recommended: ${d.recommendation})`); for (const l of authorizationLines(d)) out.push(` ${l}`); if (d.task_ref) out.push(` task: ${d.task_ref}`); out.push(` decide: mosaic decide ${shortId(d.id)}