feat: clarify approval proof composition

This commit is contained in:
lda
2026-07-10 08:23:45 +07:00 Verified
parent 7d3f665808
commit 377c39d109
4 changed files with 93 additions and 7 deletions
@@ -141,6 +141,30 @@ describe("GuidedProductMoment", () => {
expect(screen.getByRole("group", { name: /operator resume decision/i })).toBeInTheDocument(); expect(screen.getByRole("group", { name: /operator resume decision/i })).toBeInTheDocument();
}); });
it("approval uses a compact input rail and a dominant interrupt report", () => {
render(
<GuidedProductMoment
beat={findBeat("typed-human-boundary", "approval")!}
demo={demo}
contract={contract}
operation={null}
approvalActions={{
state: "ready",
canSubmit: true,
canCancel: true,
submit: vi.fn(async () => {}),
cancel: vi.fn(async () => {}),
}}
openEvidence={vi.fn()}
/>,
);
expect(screen.getByRole("region", { name: /workflow input summary/i })).toHaveAttribute("data-density", "compact");
expect(screen.getByRole("region", { name: /interrupt report and proposed issues/i })).toHaveAttribute("data-priority", "primary");
expect(screen.getByRole("group", { name: /operator resume decision/i })).toBeInTheDocument();
expect(screen.queryByText("Output")).not.toBeInTheDocument();
});
it("approval shows input, interrupt payload, and decision but no output or trace", () => { it("approval shows input, interrupt payload, and decision but no output or trace", () => {
render( render(
<GuidedProductMoment <GuidedProductMoment
@@ -65,8 +65,10 @@ export const GuidedProductMoment = ({
<div className="guided-product-moment__primary"> <div className="guided-product-moment__primary">
{moment === "approval" && contract ? ( {moment === "approval" && contract ? (
<div className="guided-product-moment__approval-grid"> <div className="guided-product-moment__approval-grid">
<RunInputFacts facts={facts} /> <aside className="guided-product-moment__input-rail" aria-label="workflow input context">
<InterruptPayloadFacts facts={facts} /> <RunInputFacts facts={facts} density="compact" />
</aside>
<InterruptPayloadFacts facts={facts} priority="primary" />
<InterruptDecisionForm <InterruptDecisionForm
interrupt={facts.interrupt} interrupt={facts.interrupt}
runId={demo.state.events.find((e) => e.stage === "run_start")?.resultingIds.runId ?? "unknown"} runId={demo.state.events.find((e) => e.stage === "run_start")?.resultingIds.runId ?? "unknown"}
@@ -3,10 +3,15 @@ import type { DemoRunFacts } from "./demo-run-facts.js";
type RunInputFactsProps = { type RunInputFactsProps = {
readonly facts: DemoRunFacts; readonly facts: DemoRunFacts;
readonly density?: "normal" | "compact";
}; };
export const RunInputFacts = ({ facts }: RunInputFactsProps) => ( type InterruptPayloadFactsProps = RunInputFactsProps & {
<div className="run-facts-card"> readonly priority?: "normal" | "primary";
};
export const RunInputFacts = ({ facts, density = "normal" }: RunInputFactsProps) => (
<div className="run-facts-card" role="region" aria-label="workflow input summary" data-density={density}>
<h3>Workflow input</h3> <h3>Workflow input</h3>
<dl className="run-facts-dl"> <dl className="run-facts-dl">
<dt>Selected documents</dt> <dt>Selected documents</dt>
@@ -32,8 +37,13 @@ const displayPayloadValue = (value: unknown): string => {
return String(value); return String(value);
}; };
export const InterruptPayloadFacts = ({ facts }: RunInputFactsProps) => ( export const InterruptPayloadFacts = ({ facts, priority = "normal" }: InterruptPayloadFactsProps) => (
<div className="run-facts-card run-facts-card--interrupt"> <div
className="run-facts-card run-facts-card--interrupt"
role="region"
aria-label="interrupt report and proposed issues"
data-priority={priority}
>
<h3>Interrupt payload</h3> <h3>Interrupt payload</h3>
<dl className="run-facts-dl run-facts-dl--inline"> <dl className="run-facts-dl run-facts-dl--inline">
<dt>Kind</dt><dd>{facts.interrupt.kind}</dd> <dt>Kind</dt><dd>{facts.interrupt.kind}</dd>
@@ -1259,11 +1259,61 @@
.guided-product-moment__approval-grid { .guided-product-moment__approval-grid {
display: grid; display: grid;
grid-template-columns: minmax(13rem, 0.55fr) minmax(0, 1.2fr) minmax(18rem, 0.75fr); grid-template-columns: minmax(11rem, 0.36fr) minmax(0, 1.35fr) minmax(20rem, 0.62fr);
gap: 0.85rem; gap: 0.85rem;
min-height: 0; min-height: 0;
} }
.guided-product-moment__input-rail {
min-width: 0;
min-height: 0;
}
.run-facts-card[data-density="compact"] {
padding: 0.8rem;
font-size: 0.82rem;
}
.run-facts-card[data-density="compact"] .run-facts-list {
gap: 0.28rem;
}
.run-facts-list--issues {
display: grid;
gap: 0.4rem;
padding: 0;
list-style: none;
}
.run-facts-list--issues li {
display: flex;
gap: 0.5rem;
align-items: center;
justify-content: space-between;
padding: 0.35rem 0.45rem;
border: 1px solid var(--stage-line);
border-radius: 0.5rem;
background: oklch(0.12 0.026 250 / 0.9);
}
.run-facts-list--issues li strong {
color: var(--text-primary);
}
.run-facts-list--issues li small {
color: var(--accent-amber);
font: 650 0.6rem/1 var(--font-mono, monospace);
}
.run-facts-card--interrupt[data-priority="primary"] {
display: grid;
grid-template-rows: auto minmax(0, 1fr) auto;
}
.run-facts-card--interrupt[data-priority="primary"] .run-facts-scroll-region--report {
min-height: 14rem;
}
.guided-product-moment__resume-grid { .guided-product-moment__resume-grid {
display: grid; display: grid;
grid-template-columns: minmax(18rem, 0.85fr) minmax(14rem, 0.45fr) minmax(0, 1fr); grid-template-columns: minmax(18rem, 0.85fr) minmax(14rem, 0.45fr) minmax(0, 1fr);