MalloryEstate Briefing
M·012Approved
← All briefings

Context & Investigations

In-Feed Brief

"What can I do?" stops opening a settings-style modal and instead drops a transient brief panel into the conversation feed, sourced live from the Wave 1-A capability registry.

Dated 2026-06-12Programme Context & Investigations

Situation

Wave 1-B. The home/empty state and the "Briefing" help sheet both describe Mallory's capabilities in hand-written prose, disconnected from each other and, until Wave 1-A, from the truth. The modal help sheet reads as a settings panel, not as Mallory presenting himself.

Decided in brainstorming: the brief is menu-triggered and rendered in the feed, not auto-shown and not a modal. The empty/calm state stays unchanged; the existing "What can I do?" menu item instead appends a brief panel as a block in the feed and scrolls to it, and the modal helpOpen overlay is retired outright.

Key decisions

In-feed, not modal

"What can I do?" appends a transient brief block to the conversation and scrolls to it; the helpOpen overlay, its hardcoded list, and its styles are removed.

Registry-sourced content

A new GET /capabilities endpoint maps CAPABILITIES to {id, label} partitioned by built/not-yet — label is a new UI-voiced field distinct from the persona's claim, so it can't drift from the registry.

Presentation is web-side only

A thin PRESENTATION map keyed by id assigns grouping/icon — visual concern only; an unmapped id still surfaces under a default group rather than being silently dropped.

Transient, never persisted

The panel is a local UI item, not inserted into session.messages — never sent to the model, never written to D1, never replayed on reload.

Graceful fallback

loadCapabilities() returns a small built-in fallback set if the fetch fails, clearly a backstop rather than the source of truth.

Architecture

A new browser-facing route exposes the registry; the web side gets a presentation-only panel component wired through the existing menu.

src/capabilities.ts
Adds a label field to Capability and every entry, alongside the existing persona-voiced claim.
src/routes/capabilities.ts
handleGetCapabilities — new GET /capabilities, gated like other browser GET routes, returns built/not-yet partitions.
web/src/lib/api.ts
loadCapabilities() — fetch, cache in a small store, fallback set on failure.
web/src/lib/components/BriefPanel.svelte
"At your service" card: built capabilities as lines with a leading icon, one muted "Not yet" summary line, plus the presentation map.
web/src/routes/+page.svelte
Menu rewire: renders the transient block at the end of the stream instead of opening helpOpen; removes the modal markup and dead styles.

Risks & guardrails

Two label fields on Capability

claim and label are mild redundancy but serve genuinely different audiences (model vs Alex) — both live in one registry, so neither drifts.

Empty-state summon

Tapping the menu from the empty state shows the block above the composer and may scroll the greeting up — accepted.

Duplicate renders

Reactivity must not duplicate the block on repeated taps; guarded with an idempotent flag rather than pushing again.

Delivery

Registry label

Add UI label to the registry + a uiCapabilities() helper.

Endpoint

GET /capabilities route.

Web client

loadCapabilities() + types + fallback.

Panel

Brief ordering helper + BriefPanel.svelte.

Feed wiring

Wire into the feed; retire the modal entirely.

Out of scope

Redesigning the empty/calm stateLive data in the brief, e.g. "3 tasks today" (Wave 1-C)General rich-feed-blocks infrastructure (Wave 2 #10) — this is one bespoke block, not the framework
spec · docs/superpowers/specs/2026-06-12-in-feed-brief-design.md
plan · docs/superpowers/plans/2026-06-12-in-feed-brief.md
Mallory · Estate briefing