architect: remove LP Objections page — generic/unverifiable output (v0.1.0:67)

The summarize-historical-email grounding produced generic, boilerplate objections
with no quotes and no source traceability (the minimize step abstracts away the
actual email text; the newest-N corpus carries little real objection signal, so the
model pattern-completes). Pulled the page (ObjectionsPage component + nav + dispatch).
The redaction boundary is kept (reusable for proactive outreach); the dormant
/api/architect/ground route is left in place but has no UI trigger. Pivoting to
proactive outreach / messaging.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Keysat
2026-06-08 19:09:58 -05:00
parent c2b84a1f26
commit 0943aeb2df
4 changed files with 23 additions and 97 deletions
-93
View File
@@ -9948,92 +9948,6 @@
);
};
const ObjectionsPage = ({ token, user, onShowToast }) => {
const isAdmin = user?.role === 'admin';
const [segment, setSegment] = useState('');
const [running, setRunning] = useState(false);
const [result, setResult] = useState(null);
const SEGMENTS = [
['', 'All LPs'],
['btc_native_hnwi', 'Bitcoin-native HNWIs'],
['institution', 'Institutions'],
['family_office', 'Family offices'],
['smaller_accredited', 'Smaller accredited ($100k)'],
['ai_energy_operator', 'AI & energy operators'],
];
const FAIL = {
local_model_unavailable: 'The local model (Spark) is unavailable, so nothing was sent to Claude. Try again once it is reachable.',
scrub_unavailable: 'The redaction boundary could not be prepared, so nothing was sent to Claude.',
claude_not_configured: 'The Architect (Claude) is not configured on the server.',
rehydrate_failed: 'Claude returned an unexpected placeholder; the draft was quarantined for safety. Nothing de-anonymized was shown.',
};
const run = async () => {
if (running) return;
try {
setRunning(true);
setResult(null);
const res = await api('/api/architect/ground', {
method: 'POST',
body: JSON.stringify(segment ? { segment_key: segment } : {}),
}, token);
setResult(res.data || res);
} catch (err) {
const msg = getErrorMessage(err, 'Grounding failed');
setResult({ status: 'error', reason: msg });
onShowToast(msg, 'error');
} finally {
setRunning(false);
}
};
if (!isAdmin) return <div className="empty-state">Admin only.</div>;
const ok = result && result.status === 'ok';
return (
<div className="page-container">
<h2 className="section-title" style={{ marginBottom: '20px' }}>LP Objections</h2>
<div className="section">
<div className="index-action-hint" style={{ marginTop: 0, marginBottom: '12px' }}>
The Architect reads your matched LP emails and notes on the local model, removes every identifier through the redaction boundary, and asks Claude for the recurring objections and the strongest honest rebuttals. Only de-identified themes ever leave Ten31 — no names, firms, amounts, or addresses. Results are a draft for your review.
</div>
<div className="index-action-buttons" style={{ alignItems: 'center' }}>
<select className="select-input" value={segment} onChange={(e) => setSegment(e.target.value)} style={{ maxWidth: '260px' }}>
{SEGMENTS.map(([v, l]) => <option key={v} value={v}>{l}</option>)}
</select>
<button onClick={run} disabled={running}>
{running ? 'Grounding… (this can take a minute)' : 'Run grounding'}
</button>
</div>
</div>
{running && <div className="section"><SkeletonBlock lines={6} /></div>}
{result && !running && (
<div className="section">
{ok ? (
<>
<div className="section-title" style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
Recurring objections &amp; rebuttals
{result.scrub_stats && result.scrub_stats.tokens != null
? <span className="approval-pill">{result.scrub_stats.tokens} identifiers protected</span> : null}
</div>
<pre style={{ whiteSpace: 'pre-wrap', fontFamily: 'inherit', lineHeight: 1.55, margin: 0 }}>{result.draft}</pre>
<div className="index-action-hint" style={{ marginTop: '12px' }}>
Draft for review. Use these to pressure-test the thesis in the Workshop.
</div>
</>
) : (
<div className="toast error" style={{ position: 'static' }}>
{FAIL[result.status] || result.reason || 'Grounding did not complete.'}
</div>
)}
</div>
)}
</div>
);
};
const EmailCapturePage = ({ token, user, onShowToast }) => {
const isAdmin = user?.role === 'admin';
const [status, setStatus] = useState(null);
@@ -10837,11 +10751,6 @@
<button className={`nav-item ${page === 'thesis-workshop' ? 'active' : ''}`} onClick={() => setPage('thesis-workshop')}>
<span className="nav-item-icon"></span> Thesis Workshop
</button>
{user?.role === 'admin' && (
<button className={`nav-item ${page === 'objections' ? 'active' : ''}`} onClick={() => setPage('objections')}>
<span className="nav-item-icon"></span> LP Objections
</button>
)}
<button className={`nav-item ${page === 'system-status' ? 'active' : ''}`} onClick={() => setPage('system-status')}>
<span className="nav-item-icon"></span> System Status
</button>
@@ -10877,7 +10786,6 @@
{page === 'communications' && 'Communications'}
{page === 'thesis' && 'Thesis'}
{page === 'thesis-workshop' && 'Thesis Workshop'}
{page === 'objections' && 'LP Objections'}
{page === 'system-status' && 'System Status'}
{page === 'email-capture' && 'Email Capture'}
{page === 'feature-requests' && 'Feature Requests'}
@@ -10910,7 +10818,6 @@
{page === 'communications' && <CommunicationsPage token={token} onShowToast={showToast} />}
{page === 'thesis' && <ThesisPage token={token} user={user} onShowToast={showToast} />}
{page === 'thesis-workshop' && <ThesisWorkshopPage token={token} user={user} onShowToast={showToast} />}
{page === 'objections' && <ObjectionsPage token={token} user={user} onShowToast={showToast} />}
{page === 'system-status' && <SystemStatusPage token={token} user={user} onShowToast={showToast} />}
{page === 'email-capture' && <EmailCapturePage token={token} user={user} onShowToast={showToast} />}
{page === 'feature-requests' && <FeatureRequestsPage token={token} onShowToast={showToast} user={user} />}