fix: harden presentation trace evidence

This commit is contained in:
lda
2026-07-11 08:46:57 +07:00 Verified
parent 7cbe7b280b
commit a03032027d
7 changed files with 70 additions and 1 deletions
@@ -332,6 +332,14 @@ describe("useDemoTimeline", () => {
expect(result.current.state.phase).toBe("completed");
expect(result.current.trace?.frames).toHaveLength(1);
expect(mockedCallOperation.mock.calls.map(([operation]) => operation)).toEqual([
"workflow.deployments.inspect",
"workflow.runs.start",
"workflow.runs.resume",
"workflow.runs.trace",
]);
await act(async () => vi.advanceTimersByTimeAsync(1800));
expect(mockedCallOperation).toHaveBeenCalledTimes(4);
});
it("shows a failed phase when a live operation rejects", async () => {
@@ -441,6 +449,20 @@ describe("useDemoTimeline", () => {
expect(result.current.state.events[result.current.state.appliedCount - 1]?.stage).toBe("run_resume");
});
it("primes replay to trace_read with all canonical trace frames", () => {
const { result } = renderHook(() => useDemoTimeline("http://127.0.0.1:8765/rpc", vi.fn()));
act(() => result.current.start("replay"));
act(() => result.current.primeReplayToStage("trace_read"));
expect(result.current.state.events[result.current.state.appliedCount - 1]?.stage).toBe("trace_read");
expect(result.current.trace?.frames.map((frame) => frame.nodeId)).toEqual([
"list_documents",
"review_issues",
"finalise_report",
]);
});
it("does not prime live timelines", () => {
const { result } = renderHook(() => useDemoTimeline("http://127.0.0.1:8765/rpc", vi.fn()));
@@ -366,6 +366,22 @@ describe("PresentationRoute", () => {
expect(await screen.findByRole("region", { name: /workflow trace frames/i })).toBeInTheDocument();
expect(screen.queryByText("No trace frames captured.")).not.toBeInTheDocument();
expect(screen.getByText("list_documents")).toBeInTheDocument();
expect(screen.getByText("review_issues")).toBeInTheDocument();
expect(screen.getByText("finalise_report")).toBeInTheDocument();
});
it("keeps trace frames when navigating from output to trace", async () => {
window.location.hash = "#scene/resume-output-evidence/output";
const { PresentationRoute } = await import("./PresentationRoute.js");
render(<PresentationRoute />);
expect(await screen.findByRole("region", { name: /workflow output report/i })).toBeInTheDocument();
window.location.hash = "#scene/resume-output-evidence/trace";
fireEvent(window, new Event("hashchange"));
expect(await screen.findByText("finalise_report")).toBeInTheDocument();
expect(screen.queryByText("No trace frames captured.")).not.toBeInTheDocument();
});
it("navigates to Scene 8 request beat via hash", async () => {
@@ -232,6 +232,7 @@ describe("RunTraceFacts", () => {
expect(screen.getByText("list_documents")).toBeDefined();
expect(screen.getByText("review_issues")).toBeDefined();
expect(screen.getByText("2 captured")).toBeInTheDocument();
expect(screen.getAllByText("captured as empty object").length).toBeGreaterThanOrEqual(2);
});
@@ -140,7 +140,9 @@ type RunTraceFactsProps = {
export const RunTraceFacts = ({ facts }: RunTraceFactsProps) => (
<div className="run-facts-card run-trace-facts" role="region" aria-label="workflow trace proof">
<h3>Trace frames</h3>
<h3>
Trace frames <span className="run-facts-count">{facts.trace.frames.length} captured</span>
</h3>
{facts.trace.frames.length === 0 ? (
<p>No trace frames captured.</p>
) : (
@@ -2206,6 +2206,13 @@
color: var(--accent-cyan);
}
.run-facts-count {
margin-left: 0.4rem;
color: var(--text-muted);
font-size: 0.72em;
font-weight: 500;
}
.run-facts-dl {
display: grid;
grid-template-columns: auto 1fr;
@@ -1453,4 +1453,23 @@
.guided-product-moment__trace-grid {
grid-template-columns: minmax(0, 1fr);
}
.guided-product-moment[data-moment="trace"] .guided-product-moment__trace-grid {
grid-template-rows: minmax(0, 1fr) auto;
}
.guided-product-moment[data-moment="trace"] .run-facts-card[data-output-priority="summary"] {
max-height: 7.25rem;
overflow: auto;
padding: 0.65rem 0.8rem;
}
.guided-product-moment[data-moment="trace"] .run-facts-card[data-output-priority="summary"] h3 {
margin-bottom: 0.4rem;
}
.guided-product-moment[data-moment="trace"] .run-facts-card[data-output-priority="summary"] .run-facts-dl {
gap: 0.2rem 0.55rem;
font-size: 0.76rem;
}
}