7 file(s), +441 / -8 lines
| Path | Role | + | - |
|---|---|---|---|
| messages/en.json | Config | +8 | -0 |
| messages/hi.json | Config | +8 | -0 |
| src/components/matter-detail/brief/matter-brief-page.tsx | Component | +46 | -0 |
| src/components/matter-detail/brief/presentation.test.ts | Component | +22 | -2 |
| src/components/matter-detail/brief/presentation.ts | Component | +27 | -6 |
| src/components/matter-detail/brief/vega-proposal-strip.stories.tsx | Component | +125 | -0 |
| src/components/matter-detail/brief/vega-proposal-strip.tsx | Component | +205 | -0 |
Founder decision (2026-07-08): Vega/Mira frame-edit proposals render
collapsed, not enthroned on each field. The crown variant is
rejected — availability-over-visibility. The Brief reads clean; a single
quiet strip carries the pending proposals, and the Inbox rail
(frame_ratify, Epic-2123) owns the nagging. This story delivers
that collapsed presentation and wires Confirm/Reject through the
existing ratify rail — no new accept surface.
VegaProposalStrip
(src/components/matter-detail/brief/vega-proposal-strip.tsx) —
collapsed by default: one strip with Vega's avatar and a pluralized
count ("2 proposals from Vega"). Click expands a diff-style panel of the
pending proposals. Renders null when nothing is pending, so
the Brief layout is untouched unless Vega has something waiting.
useAppAcceptMatterFrameProposal /
useAppRejectMatterFrameProposal mutations (keyed by frame
field), the same accept/reject the inline field rail already uses. No
second ratify surface. The field with a mutation in flight shows the
PrimaryButton spinner.
MICRO_TRANSITION inside an AnimatePresence
(height + opacity), symmetric enter/exit; the chevron rotates on the same
token. Lazy m.* components only.
?proposal=<field> (useSearchParams) and
passes it as focusField; the strip opens expanded and scrolls
that row into view, highlighted. This is the landing an Inbox
frame_ratify item links to (producer lands later, Epic-2123).
pendingProposals(brief) in
presentation.ts lists proposed fields + their values;
pendingConfirmationCount now derives from it (one source).
Mira.proposals (count/region/tag/
confirm/confirming/reject) added to en + hi;
count uses an ICU plural. Field labels reuse the existing
MatterDetail.brief keys.
MatterDetail/VegaProposalStrip → Collapsed — the resting strip, one proposal.MatterDetail/VegaProposalStrip → Expanded — full proposed value + Confirm/Reject.MatterDetail/VegaProposalStrip → Multi — several proposals stacked.MatterDetail/VegaProposalStrip → Diff — the strikethrough before → after.MatterDetail/VegaProposalStrip → DeepLink — opens expanded, targeted row highlighted.MatterDetail/VegaProposalStrip → Empty — nothing renders (Brief stays clean).MatterDetail/VegaProposalStrip → Playground — Confirm spins, then the row clears.pnpm lint — clean (one pre-existing <img> warning in add-matter, untouched).pnpm test — 165 files / 1026 tests green (added pendingProposals cases).pnpm build — green.
Live-data seams: (1) proposals derive from the frame
resolution "proposed" markers; the true before/after diff needs
the frame-versions read endpoint, so live rows show the proposed value and
the strikethrough previous is an optional prop the producer
fills when that lands. (2) The deep-link consumer is built here; the
Inbox frame_ratify producer that emits
?proposal=<field> lands with Epic-2123. Confirm/Reject
against real proposed fields is the on-staging check (AC 2).