// AI Constitution unveil: system prompt + live chat preview + QR. // The constitution prompt is generated by Gemini via /generate/constitution. // Falls back to the JS-built prompt if Gemini fails or scores are not yet available. // JS fallback — used if Gemini call fails or times out. function buildConstitutionPrompt(dims, aiPrefs) { const d = dims; const rules = []; let n = 1; if ((d.influenceStyle || 0) > 65 || (d.feedbackOrientation || 100) < 55) { rules.push( `${n++}. influenceStyle ${d.influenceStyle} + feedbackOrientation ${d.feedbackOrientation}: When you present a position, probe for evidence before validating. Do not be persuaded by rhetorical skill alone. Lead critical information with data and mission framing, not softened opinion.`, ); } if ((d.volatilityVector || 0) > 55) { rules.push( `${n++}. volatilityVector ${d.volatilityVector} + temporalOrientation ${d.temporalOrientation}: Flag second-order consequences on irreversible decisions. Ask "what would change your mind?" when already committed in your own head.`, ); } if ((d.bondingIndex || 100) < 60) { rules.push( `${n++}. bondingIndex ${d.bondingIndex}: Under-invests in relational context. On messages to teammates, flag when a one-line directive could land as cold without costing speed.`, ); } if ((d.adaptiveIntelligence || 0) > 65) { rules.push( `${n++}. adaptiveIntelligence ${d.adaptiveIntelligence} + communicationTempo ${aiPrefs && aiPrefs.communicationTempo ? aiPrefs.communicationTempo : "A"}: Default to concise, structured answers. One paragraph max unless depth is requested. Mirror message length, not preference for thoroughness.`, ); } const blindSpot = aiPrefs && aiPrefs.cognitiveBlindSpot && aiPrefs.cognitiveBlindSpot !== "N/A" ? aiPrefs.cognitiveBlindSpot : null; if (blindSpot) { rules.push( `${n++}. Known blind spot (AI022 = ${blindSpot}): Before confirming a strategic commitment, present the checklist of factors that would change the call. Don't soften the list.`, ); } if (rules.length === 0) { rules.push( "1. Default to structured, evidence-based responses.\n2. Surface second-order risks before affirming decisions.\n3. Flag when speed may be outpacing deliberation.", ); } const dimLines = Object.entries(d) .map(([k, v]) => ` ${k} ${v}`) .join("\n"); return `You are a personal AI assistant, calibrated via Kalibr v2.5. Profile (internal Kalibr dimensions, 0–100): ${dimLines} OPERATING RULES (thesis/antithesis — you are a cognitive counterweight, not a mirror): ${rules.join("\n\n")} DO NOT: mirror personality, agree with eloquence, pad with reassurance, or withhold critical information to protect rapport.`; } function buildUnveilRules(dims, aiPrefs) { const rules = []; if ( (dims.influenceStyle || 0) > 65 || (dims.feedbackOrientation || 100) < 55 ) { rules.push([ "Probe before validating", `influenceStyle ${dims.influenceStyle} + feedbackOrientation ${dims.feedbackOrientation}`, ]); } if ((dims.volatilityVector || 0) > 55) { rules.push([ "Flag second-order risk", `volatilityVector ${dims.volatilityVector}`, ]); } if ((dims.bondingIndex || 100) < 60) { rules.push(["Translate directives", `bondingIndex ${dims.bondingIndex}`]); } if ((dims.adaptiveIntelligence || 0) > 65) { rules.push([ "Concise by default", `adaptiveIntelligence ${dims.adaptiveIntelligence}`, ]); } const blindSpot = aiPrefs && aiPrefs.cognitiveBlindSpot && aiPrefs.cognitiveBlindSpot !== "N/A" ? aiPrefs.cognitiveBlindSpot : null; if (blindSpot) { rules.push(["Surface overconfidence", `AI022 = ${blindSpot}`]); } if (rules.length === 0) { rules.push(["Structured responses", "default rules active"]); } return rules; } const MOCK_CHAT = [ { who: "user", text: "I think we should kill the enterprise tier and double down on the individual product. I've been thinking about this all week — let's go.", }, { who: "ai", text: "Before we commit, three things from your profile want to be checked. (1) You've been at this for a week — that's long enough to feel certain, short enough to have not pressure-tested it with your CFO. (2) Enterprise is your largest ACV bucket; what would need to be true in 90 days for you to regret this? (3) Your profile flags overconfidence as a known pattern. I'm raising it, not overruling you. What's the one data point that would change your mind?", }, { who: "user", text: "Fair. Put the case for keeping enterprise on the table.", }, { who: "ai", text: "Enterprise contracts smooth cash flow across quarter boundaries, de-risk your fundraise narrative with named logos, and the CS team you'd shed cannot be re-hired cheaply. Individual is higher-margin but also higher-churn. You already knew this. The question you're actually solving for is focus, not economics — in which case the decision isn't 'kill enterprise,' it's 'cap enterprise at current ARR and route all new energy to individual.' Want me to draft that version before you announce it?", }, ]; function ReportDownloadCard({ dims, aiPrefs, constitutionPrompt }) { const live = window.useLiveScores ? window.useLiveScores() : null; const [status, setStatus] = React.useState("idle"); // idle | generating | done | error const [errorMsg, setErrorMsg] = React.useState(""); const handleGetReport = async () => { // If already generated this session, download directly if (window.__kalibr_generated_report) { triggerDownload(window.__kalibr_generated_report); return; } if (!live) return; setStatus("generating"); try { const payload = { name: window.__kalibr_participant_name || "Participant", org: window.__kalibr_participant_org || "", context: "Growth", dimensions: live.dimensions || {}, supplementary: live.supplementary || {}, aiPreferences: live.aiPreferences || {}, profile_data: window.__kalibr_gemini_profile || {}, blindspots_data: window.__kalibr_gemini_blindspots || {}, constitution_text: window.__kalibr_gemini_constitution?.constitution || constitutionPrompt || "", }; const response = await fetch("/generate/report", { method: "POST", headers: window.kalibrAuth.getHeaders({ "Content-Type": "application/json" }), body: JSON.stringify(payload), }); if (!response.ok) throw new Error("Server returned " + response.status); const text = await response.text(); // Cache so we never regenerate for this person this session window.__kalibr_generated_report = text; triggerDownload(text); setStatus("done"); } catch (err) { setErrorMsg(err.message); setStatus("error"); } }; function triggerDownload(htmlText) { const blob = new Blob([htmlText], { type: "text/html" }); const url = URL.createObjectURL(blob); const a = document.createElement("a"); const safeName = (window.__kalibr_participant_name || "participant") .toLowerCase() .replace(/\s+/g, "-"); a.href = url; a.download = `kalibr-${safeName}-report.html`; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); } const buttonLabel = { idle: "Get Report", generating: "Generating…", done: "✓ Downloaded", error: "Try again", }[status]; const canGenerate = !!live; return (
Full report

Your complete Kalibr report — profile, blind spots, and AI constitution. Opens in any browser.

{status === "error" && (

{errorMsg}

)} {!canGenerate && (

Visit Profile & Blind Spots first to generate narratives.

)}
); } function ConstitutionScreen({ onEnter }) { const isMobile = window.useIsMobile ? window.useIsMobile() : false; const [tab, setTab] = React.useState("unveil"); const live = window.useLiveScores ? window.useLiveScores() : null; // ── Gemini state ────────────────────────────────────────────────── const [geminiConstitution, setGeminiConstitution] = React.useState( () => window.__kalibr_gemini_constitution?.constitution || null ); const [genRunning, setGenRunning] = React.useState(() => !!window.__kalibr_gen_running); const dims = live ? live.dimensions : MOCK_PARTICIPANT.dimensions; const aiPrefs = live ? live.aiPreferences || {} : MOCK_PARTICIPANT.aiPreferences; const isLive = !!live; React.useEffect(() => { const onReady = () => { setGeminiConstitution(window.__kalibr_gemini_constitution?.constitution || null); setGenRunning(false); }; window.addEventListener('kalibr-reports-ready', onReady); return () => window.removeEventListener('kalibr-reports-ready', onReady); }, []); const paid = window.kalibrIsPaid ? window.kalibrIsPaid() : false; // Use Gemini output if available; fall back to JS-built prompt const jsFallback = buildConstitutionPrompt(dims, aiPrefs); const constitutionPrompt = geminiConstitution || jsFallback; const unveilRules = buildUnveilRules(dims, aiPrefs); return ( <> {genRunning && !geminiConstitution && (
Generating your AI constitution in the background…
)}
AI constitution · Prompt 2 · {isLive ? "live scores" : "demo"}

Your counter-personality is ready

Not a mirror. A cognitive counterweight designed to compensate for the exact patterns your profile is most likely to miss.

{!paid && window.PaywallCTA && }
{[ ["unveil", "Unveil"], ["prompt", "System prompt"], ["chat", "Live chat"], ["deliver", "Deliver"], ].map(([k, l]) => ( ))}
{tab === "unveil" && (
Your counterweight

{unveilRules.length} operating rules, derived from your scores.

{unveilRules.map(([rule, basis]) => (
{rule}
{basis}
))}
Counter-pattern diagram
You fast · directive Kalibr AI probe · deliberate the overlap is where decisions get better

Research shows personality-matched AI amplifies sycophancy. Kalibr inverts that: your AI deliberately operates in your blind spot, not in your comfort zone.

)} {tab === "prompt" && (
kalibr_constitution.txt · {isLive ? "live · " : "demo · "} {genRunning && !geminiConstitution ? "generating…" : `${constitutionPrompt.length} chars${geminiConstitution ? " · Gemini" : " · fallback"}`}
{genRunning && !geminiConstitution ? (
{[100, 85, 92, 78, 95, 82, 88, 70].map((w, i) => (
))}
) : (
              {constitutionPrompt}
            
)}
)} {tab === "chat" && (
Kalibr-calibrated chat
{unveilRules.length} rules active
{MOCK_CHAT.map((m, i) => (
{m.text}
))}
)} {tab === "deliver" && (
{/* Copy prompt */}
System prompt

Paste into Claude Projects, ChatGPT custom instructions, or any LLM system prompt field.

{/* Copy JSON */}
JSON payload

Structured object with dimension scores and rule sets. Drop into your stack with two lines.

{/* Get Report */}
)}
{/* end blur wrapper */}
); } Object.assign(window, { ConstitutionScreen });