diff --git a/solstone/apps/thinking/static/thinking.js b/solstone/apps/thinking/static/thinking.js index aff3643e3..9ecdf9128 100644 --- a/solstone/apps/thinking/static/thinking.js +++ b/solstone/apps/thinking/static/thinking.js @@ -225,6 +225,20 @@ return {text: message, hidden: !message}; } + function confidentialSetupOperationLines(operation, text, attestationMessage = '') { + const rendered = confidentialOperationRender(operation, text); + const notice = confidentialNoticeLine(operation, text); + if (!notice.hidden) { + return {state: attestationMessage, operation: '', operationTone: '', notice}; + } + return { + state: rendered.message || attestationMessage, + operation: rendered.message || '', + operationTone: rendered.tone, + notice, + }; + } + function confidentialAttestationRender(attestation, text, checkedLabel = '') { const stateName = attestation?.state || 'off'; const states = text?.attestation_states || {}; @@ -766,7 +780,7 @@ const confidentialCopy = copy.confidential || {}; const checked = confidentialCheckedLabel(attestation); const rendered = confidentialAttestationRender(attestation, confidentialCopy, checked); - const operationRendered = confidentialOperationRender(operation, confidentialCopy); + const lines = confidentialSetupOperationLines(operation, confidentialCopy, rendered.message); const operationActive = !!operation && !confidentialOperationIsTerminal(operation); const phase = operation?.phase || ''; @@ -776,22 +790,21 @@ operationActive ? phase : rendered.pill, operationActive ? '' : rendered.tone, ); - setText('confidentialSetupState', operationRendered.message || rendered.message); + setText('confidentialSetupState', lines.state); const lastChecked = relativeTime(attestation.last_verified?.checked_at || ''); setText('confidentialSetupMeta', confidentialSetupMetaLine(attestation, lastChecked)); setMessage( 'confidentialLaneOperation', - operationRendered.message || '', - operationRendered.tone, + lines.operation, + lines.operationTone, ); setLink( 'confidentialLaneOperationLink', operation?.portal_url || '', 'continue in browser →', ); - const notice = confidentialNoticeLine(operation, confidentialCopy); - setText('confidentialNotice', notice.text); - setHidden('confidentialNotice', notice.hidden); + setText('confidentialNotice', lines.notice.text); + setHidden('confidentialNotice', lines.notice.hidden); setButtonState('confidentialEnable', !configured && !operationActive, operationActive); setButtonText('confidentialEnable', confidentialCopy.actions?.off || ''); setButtonState('confidentialDisable', configured, operationActive || !configured); diff --git a/solstone/apps/thinking/tests/test_thinking_confidential_poll_js.py b/solstone/apps/thinking/tests/test_thinking_confidential_poll_js.py index 8261e9424..7e4056a34 100644 --- a/solstone/apps/thinking/tests/test_thinking_confidential_poll_js.py +++ b/solstone/apps/thinking/tests/test_thinking_confidential_poll_js.py @@ -30,6 +30,7 @@ def _node_script(body: str) -> str: extract_js_function(source, "confidentialVerifiedValues"), extract_js_function(source, "confidentialSetupMetaLine"), extract_js_function(source, "confidentialNoticeLine"), + extract_js_function(source, "confidentialSetupOperationLines"), extract_js_function(source, "confidentialAttestationRender"), extract_js_function(source, "clearConfidentialInProgressOperation"), extract_js_function(source, "confidentialGlanceForAttestation"), @@ -151,6 +152,31 @@ for (const operation of [ assert(notice.hidden === true, `notice hidden for ${operation?.phase || 'none'}`); } +const earlyLines = confidentialSetupOperationLines( + {phase: 'early_access'}, + confidentialCopy, + '', +); +const earlySentence = 'confidential processing is coming — scouts get it first.'; +assert(earlyLines.state === '', 'early access absent from state line'); +assert(earlyLines.operation === '', 'early access absent from operation line'); +assert(earlyLines.notice.text === earlySentence, 'early access assigned to notice'); +assert( + [earlyLines.state, earlyLines.operation, earlyLines.notice.text] + .filter((line) => line === earlySentence).length === 1, + 'early access visible exactly once', +); + +for (const [phase, message] of [ + ['starting', 'opening your browser to confirm…'], + ['waiting', 'finish turning it on in your browser'], +]) { + const lines = confidentialSetupOperationLines({phase}, confidentialCopy, 'attestation'); + assert(lines.state === message, `${phase} state unchanged`); + assert(lines.operation === message, `${phase} operation unchanged`); + assert(lines.notice.hidden === true, `${phase} notice hidden`); +} + for (const provenance of [ {substrate, checked_at: '2026-07-12T12:00:00+00:00'}, {legs: ['cpu', 'gpu'], substrate: ' ', checked_at: '2026-07-12T12:00:00+00:00'},