From e25bcb9747caf44203eb9e907cb5c05beb4a7e5b Mon Sep 17 00:00:00 2001 From: OmerHarmankayaC Date: Wed, 19 Aug 2026 16:39:29 +0300 Subject: [PATCH] feat(frontend): render the not-advice caveat on model output surfaces MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The prompts already instruct the model to describe its own answers as research commentary — prompts/chat/system.md, prompts/analysis/stage2_report.md and prompts/news/system_sentiment.md each carry the line. An instruction is not a guarantee: a model that omits it, or a fallback provider that phrases it away, leaves the screen with no caveat at all. Before this change the only caveat the client rendered unconditionally was the provenance footer on the ownership board. ModelOutputNotice renders it from the client, independent of what the model chose to say, and attaches to the three surfaces that carry model output: the analysis report, the news verdict panel and the chat composer. Its styling follows the footer already in OwnershipPage rather than introducing a new one. Deliberately not a band in ClientShell. That shell is a fixed-height, non-scrolling layout, so a permanent row would cost height on all thirteen routes — including the heatmap and the live feed, which render no model output to caveat. The landing footer carries no model output either, so it gets a product-level line rather than the same component. --- frontend/components/OracleChatPage.tsx | 2 ++ frontend/components/OraclePanel.tsx | 3 +++ frontend/components/analysis/ReportView.tsx | 2 ++ frontend/components/landing/LandingFooter.tsx | 8 ++++++ frontend/components/ui/ModelOutputNotice.tsx | 26 +++++++++++++++++++ 5 files changed, 41 insertions(+) create mode 100644 frontend/components/ui/ModelOutputNotice.tsx diff --git a/frontend/components/OracleChatPage.tsx b/frontend/components/OracleChatPage.tsx index 127014e..0bdefbc 100644 --- a/frontend/components/OracleChatPage.tsx +++ b/frontend/components/OracleChatPage.tsx @@ -33,6 +33,7 @@ import { } from '@/lib/api'; import { useChatJob } from '@/hooks/queries'; import StepTimeline from './chat/StepTimeline'; +import ModelOutputNotice from '@/components/ui/ModelOutputNotice'; import { toStepRow, toStoredSteps, type ChatStep } from '@/lib/chat-job'; type ResponseStyle = 'concise' | 'detailed'; @@ -732,6 +733,7 @@ export default function OracleChatPage() { whether there is a reasoning pass — rather than the old line, which described detailed mode whichever one was selected. */}

{mode.blurb}

+ diff --git a/frontend/components/OraclePanel.tsx b/frontend/components/OraclePanel.tsx index d9b6676..43e9825 100644 --- a/frontend/components/OraclePanel.tsx +++ b/frontend/components/OraclePanel.tsx @@ -20,6 +20,7 @@ import { TrendingUp, } from 'lucide-react'; import type { EvidenceItem, NewsAnalysis, PrecedentAnalogy } from '@/lib/api'; +import ModelOutputNotice from '@/components/ui/ModelOutputNotice'; type Sentiment = 'bullish' | 'bearish' | 'neutral'; @@ -453,6 +454,8 @@ function AnalysisBody({ )} + + ); } diff --git a/frontend/components/analysis/ReportView.tsx b/frontend/components/analysis/ReportView.tsx index 654d4f4..3626e04 100644 --- a/frontend/components/analysis/ReportView.tsx +++ b/frontend/components/analysis/ReportView.tsx @@ -3,6 +3,7 @@ import { AlertTriangle, ArrowLeft, Calendar, Loader2, RotateCw } from 'lucide-react'; import type { AnalysisJob, AnalysisReport, TimeFrame } from '@/lib/api'; import ReportMarkdown from './ReportMarkdown'; +import ModelOutputNotice from '@/components/ui/ModelOutputNotice'; interface ReportViewProps { timeframe: TimeFrame; @@ -89,6 +90,7 @@ export default function ReportView({ )} + ) : (

diff --git a/frontend/components/landing/LandingFooter.tsx b/frontend/components/landing/LandingFooter.tsx index f1fe3e6..5bc5130 100644 --- a/frontend/components/landing/LandingFooter.tsx +++ b/frontend/components/landing/LandingFooter.tsx @@ -46,6 +46,14 @@ export default function LandingFooter() { + + {/* The landing page carries no model output of its own, so this states + what the product is rather than caveating a specific answer. The + per-surface notice inside the terminal is `ui/ModelOutputNotice`. */} +

+ Oracle-X is a research terminal. It reports market data and model-generated commentary — + nothing it produces is investment advice. +

); } diff --git a/frontend/components/ui/ModelOutputNotice.tsx b/frontend/components/ui/ModelOutputNotice.tsx new file mode 100644 index 0000000..08cca10 --- /dev/null +++ b/frontend/components/ui/ModelOutputNotice.tsx @@ -0,0 +1,26 @@ +/** + * The standing caveat under anything a language model wrote. + * + * The prompts already tell the model to describe its own output as research + * commentary — `prompts/chat/system.md`, `prompts/analysis/stage2_report.md` + * and `prompts/news/system_sentiment.md` all carry the line. But an instruction + * is not a guarantee: a model that omits it, or a fallback provider that + * phrases it away, leaves the screen with no caveat at all. Rendering it from + * the client makes it independent of what the model chose to say. + * + * Deliberately not a band in `ClientShell`. That shell is a fixed-height, + * non-scrolling layout, so a permanent row there would cost height on all + * thirteen routes — including the heatmap and the live feed, which show no + * model output to caveat. This attaches to the surfaces that carry it instead. + * + * The border and spacing are left to the caller: the report footer wants a rule + * above it, the chat composer already sits under one. + */ +export default function ModelOutputNotice({ className = '' }: { className?: string }) { + return ( +

+ Model-generated and can be wrong — verify anything you act on. Research commentary, not + personalised investment advice. +

+ ); +}