Skip to content

Commit 73431cc

Browse files
authored
feat: tighten home and compare control copy (#94)
1 parent 1a1d0ff commit 73431cc

6 files changed

Lines changed: 33 additions & 21 deletions

File tree

apps/dashboard/app/page.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -235,11 +235,11 @@ export default async function Home() {
235235
const latestFailureHint = firstEnglishText(latestFailure?.action_hint_zh) || "inspect failure events";
236236
const latestFailureGovernanceHref = latestFailure ? "/events" : "/runs";
237237
const latestFailureGovernanceLabel = latestFailure
238-
? `Governance entry: ${latestFailureHint}`
239-
: "Governance entry: open runs";
238+
? `Next action: ${latestFailureHint}`
239+
: "Next action: open runs";
240240
const riskSummaryTitle =
241241
hasDegradedRunsData
242-
? "Data degraded"
242+
? "Degraded inputs"
243243
: !hasRunHistory
244244
? "Waiting for first run"
245245
: failureRate >= 0.5 || latestRunIsFailed
@@ -298,17 +298,17 @@ export default async function Home() {
298298
) : null}
299299
<div className="stats-grid">
300300
<article className="metric-card">
301-
<p className="metric-label">Risk summary</p>
301+
<p className="metric-label">Operator risk bulletin</p>
302302
<p className={`metric-value ${riskSummaryClass}`}>{riskSummaryTitle}</p>
303303
<p className={`cell-sub mono ${latestRunStatusClass}`}>
304-
Latest status: {hasDegradedRunsData ? "Data degraded" : hasRunHistory ? statusLabelEn(latestRun?.status) : "No runs yet"}
304+
Current posture: {hasDegradedRunsData ? "Degraded inputs" : hasRunHistory ? statusLabelEn(latestRun?.status) : "No runs yet"}
305305
</p>
306306
<p className={`cell-sub mono ${hasDegradedRunsData ? "cell-warning" : latestFailure ? "cell-danger" : "muted"}`}>
307-
Failure category: {hasDegradedRunsData ? "unavailable while data is degraded" : String(latestFailureCategory)}
307+
Primary risk: {hasDegradedRunsData ? "run list unavailable" : String(latestFailureCategory)}
308308
</p>
309309
<p className="cell-sub mono muted">{formatLocalTime(latestRun?.last_event_ts || latestRun?.created_at)}</p>
310310
<Link href={latestFailureGovernanceHref} className="cell-sub mono">
311-
{hasDegradedRunsData ? "Governance entry: inspect data sources and the run list" : latestFailureGovernanceLabel}
311+
{hasDegradedRunsData ? "Next action: inspect data sources and the run list" : latestFailureGovernanceLabel}
312312
</Link>
313313
</article>
314314
<article className="metric-card">

apps/dashboard/app/runs/[id]/compare/page.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,11 @@ export default async function RunComparePage({
130130
const displayNextAction = hasCompareReport
131131
? decision.nextAction
132132
: "Go back to Run Detail, run replay compare, and refresh this page once the report exists.";
133+
const actionPanelTitle = hasCompareReport ? "Next operator step" : "Recovery path";
134+
const actionPanelIntro = hasCompareReport
135+
? "Use compare as a decision surface first, raw JSON second."
136+
: "No compare report exists yet, so this card stays focused on the shortest recovery path.";
137+
const choreographyTitle = hasCompareReport ? "Operator choreography" : "Observation posture";
133138
const verdictTitle = !hasCompareReport
134139
? "Observation mode only."
135140
: decision.tone === "success"
@@ -187,8 +192,8 @@ export default async function RunComparePage({
187192
</div>
188193
</Card>
189194
<Card className="compare-next-card">
190-
<h2 className="section-title">Next operator step</h2>
191-
<p className="muted">Use compare as a decision surface first, raw JSON second.</p>
195+
<h2 className="section-title">{actionPanelTitle}</h2>
196+
<p className="muted">{actionPanelIntro}</p>
192197
<p className="mono">{displayNextAction}</p>
193198
{incidentPack.summary ? <p className="mono">Incident: {String(incidentPack.summary)}</p> : null}
194199
{proofPack.summary ? <p className="mono">Proof: {String(proofPack.summary)}</p> : null}
@@ -215,7 +220,7 @@ export default async function RunComparePage({
215220
</div>
216221
</Card>
217222
<Card className="compare-archive-card">
218-
<h3>Operator choreography</h3>
223+
<h3>{choreographyTitle}</h3>
219224
<div className="stack-gap-2">
220225
<p className="muted">Keep the second card decision-oriented too. Treat this as operator choreography, not a duplicate summary.</p>
221226
<p className="mono">{hasCompareReport ? "Compare first → proof second → replay only after the verdict is clear." : "No compare report yet → return to Run Detail, generate compare, then re-open this room."}</p>

apps/dashboard/tests/home_page.test.tsx

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,8 @@ describe("dashboard home run-summary clarity", () => {
134134
"href",
135135
"https://xiaojiou176-open.github.io/OpenVibeCoding/use-cases/"
136136
);
137-
expect(screen.getByText("Risk summary")).toBeInTheDocument();
138-
expect(screen.getByRole("link", { name: "Governance entry: open runs" })).toHaveAttribute("href", "/runs");
137+
expect(screen.getByText("Operator risk bulletin")).toBeInTheDocument();
138+
expect(screen.getByRole("link", { name: "Next action: open runs" })).toHaveAttribute("href", "/runs");
139139
expect(screen.getByText("Stable: no recent failed runs (0%)")).toHaveClass("badge--success");
140140
expect(screen.getByRole("progressbar", { name: "Failure share 0/0" })).toBeInTheDocument();
141141
expect(screen.getByRole("link", { name: "View all runs" })).toHaveAttribute("href", "/runs");
@@ -277,9 +277,9 @@ describe("dashboard home run-summary clarity", () => {
277277
] as never[]);
278278

279279
render(await Home());
280-
expect(screen.getByText("Risk summary")).toBeInTheDocument();
281-
expect(screen.getByText("Failure category: Manual review required")).toBeInTheDocument();
282-
expect(screen.getByRole("link", { name: "Governance entry: inspect failure events" })).toHaveAttribute("href", "/events");
280+
expect(screen.getByText("Operator risk bulletin")).toBeInTheDocument();
281+
expect(screen.getByText("Primary risk: Manual review required")).toBeInTheDocument();
282+
expect(screen.getByRole("link", { name: "Next action: inspect failure events" })).toHaveAttribute("href", "/events");
283283
expect(screen.queryByText(/^manual$/i)).not.toBeInTheDocument();
284284
expect(screen.getByRole("link", { name: "Run run-1" })).toHaveAttribute("href", "/runs/run-1");
285285
expect(screen.getByText(/Task: task-1 · Manual review required/)).toBeInTheDocument();
@@ -411,10 +411,10 @@ describe("dashboard home run-summary clarity", () => {
411411

412412
render(await Home());
413413

414-
expect(screen.getByText("Data degraded")).toHaveClass("metric-value--warning");
415-
expect(screen.getByText("Latest status: Data degraded")).toBeInTheDocument();
416-
expect(screen.getByText("Failure category: unavailable while data is degraded")).toHaveClass("cell-warning");
417-
expect(screen.getByRole("link", { name: "Governance entry: inspect data sources and the run list" })).toHaveAttribute("href", "/runs");
414+
expect(screen.getByText("Degraded inputs")).toHaveClass("metric-value--warning");
415+
expect(screen.getByText("Current posture: Degraded inputs")).toBeInTheDocument();
416+
expect(screen.getByText("Primary risk: run list unavailable")).toHaveClass("cell-warning");
417+
expect(screen.getByRole("link", { name: "Next action: inspect data sources and the run list" })).toHaveAttribute("href", "/runs");
418418
expect(screen.getByText("Data degraded: the run list is temporarily unavailable (0%)")).toHaveClass("badge--warning");
419419
expect(screen.getByText("Total: -")).toBeInTheDocument();
420420

apps/dashboard/tests/run_compare_page.test.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,8 @@ describe("run compare decision surface", () => {
136136
expect(screen.getAllByText("Observation only").length).toBeGreaterThan(0);
137137
expect(screen.getByText(/does not have a `run_compare_report` yet/i)).toBeInTheDocument();
138138
expect(screen.getAllByText(/run replay compare, and refresh this page/i).length).toBeGreaterThan(0);
139-
expect(screen.getByText("Operator choreography")).toBeInTheDocument();
139+
expect(screen.getByText("Recovery path")).toBeInTheDocument();
140+
expect(screen.getByText("Observation posture")).toBeInTheDocument();
140141
expect(screen.getByText(/Evidence chain: Unavailable/i)).toBeInTheDocument();
141142
expect(screen.getByText("Compare posture")).toBeInTheDocument();
142143
expect(screen.getByText("Awaiting report")).toBeInTheDocument();

apps/desktop/src/pages/RunComparePage.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,10 @@ export function RunComparePage({ runId, onBack }: Props) {
109109
const displayNextAction = hasCompareReport
110110
? compareDecision.nextAction
111111
: "Go back to Run Detail, run replay compare, and refresh this surface once the compare report exists.";
112+
const actionPanelTitle = hasCompareReport ? "Key deltas" : "Recovery path";
113+
const actionPanelIntro = hasCompareReport
114+
? ""
115+
: "No compare report exists yet, so this panel stays focused on the shortest recovery path.";
112116
const verdictBadge = !hasCompareReport ? "Observation only" : compareDecision.badge;
113117
const verdictSummary = !hasCompareReport
114118
? "No structured compare report exists yet, so this room stays in observation mode."
@@ -200,8 +204,9 @@ export function RunComparePage({ runId, onBack }: Props) {
200204
</CardBody>
201205
</Card>
202206
<Card className="compare-stage-next">
203-
<CardHeader><CardTitle>Key deltas</CardTitle></CardHeader>
207+
<CardHeader><CardTitle>{actionPanelTitle}</CardTitle></CardHeader>
204208
<CardBody>
209+
{actionPanelIntro ? <p className="muted">{actionPanelIntro}</p> : null}
205210
<div className="data-list">
206211
{deltaRows.map((item) => (
207212
<div key={item.label} className="data-list-row">

design-system/pages/run-compare.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ Tell the operator:
1818
- The raw evidence archive must remain collapsed and visually subordinate.
1919
- When no compare report exists, the room must explicitly read as observation mode rather than pretending a verdict exists.
2020
- Observation mode must never show synthetic failure posture. Use `Missing`, `Pending`, or `Unavailable` until the compare report exists.
21+
- In observation mode, the second primary card should read like a `Recovery path`, not like a duplicate delta explainer.
2122

2223
## Avoid
2324

0 commit comments

Comments
 (0)