18 KiB
Gap Card — S16 Memory Review
Screen 16 in the UX-refactor blueprint deck. Onboarding step 5 ("Memory Review — approve before importing") AND the standing low-confidence review queue (Journey J08). Execution model is LOCKED: in-place incremental refactor of
apps/web+ targeted backend extension. Every claim below is grounded in repo source.
1. Screen & purpose
Purpose (PRD §12.12 step 5; Blueprint screen 16, line 392-399): the trust gate before memory becomes active. After the user connects/imports sources (S15 Memory Import), Waggle has parsed-but-not-committed items. S16 lets the user review what was found, by category, with source and confidence, and explicitly approve (or edit/skip) before anything is written to active memory.
- Blueprint mental model (line 55-57): the Understand layer "classify, deduplicate, extract entities, map relationships and score confidence" — "Memory Review shows categories, source and confidence."
- Two entry points, same surface:
- Onboarding (J01 First-time setup):
… → Memory Import → Memory Review → Workspace Creation. - Standing low-confidence queue (J08):
Home alert → Memory Review queue → inspect evidence → approve/edit/rejectso "uncertain memory does not silently influence work."
- Onboarding (J01 First-time setup):
- Mockup (
screen_16_memory_review.png, directional only): header "Review before importing"; 5 category stat tiles Memories 342 / Decisions 56 / Tasks 32 / Artifacts 41 / Projects 17; a category-tabbed table (Memories | Decisions | Tasks | Artifacts | Projects) of rows with Content / Type / Source / Confidence columns; search + Filters; right rail "Import summary" (per-category counts), "Top sources" (Claude/ChatGPT/Google Docs/Notion with item counts), and a "Confidence guide" legend; footer actions Back / Skip for now / Edit selections / Approved & import ABS items.
PRD acceptance criteria win over pixels (§24). The load-bearing ACs:
- §12.12: "Nothing imports without explicit review/approval."
- Blueprint S16 acceptance: "Trust gate before memory becomes active."
- J08: "Uncertain memory does not silently influence work."
2. Required states (PRD / Blueprint)
Blueprint S16 states (line 396-397) + onboarding row (line 474-476):
| State | Meaning |
|---|---|
| Empty | No items found / nothing to review (source had no recognizable content). |
| Preview found | Parsed items shown, grouped by category, awaiting approval. |
| Low confidence | Subset surfaced as uncertain — must be inspectable (evidence) and individually approve/edit/reject (J08). |
| Source error | A source failed to parse/connect; offer retry-source. |
| Approved | User approved; commit runs (progress) → items become active memory. |
| Import partial | Onboarding state: some sources imported, some failed/skipped. |
Required interactions (line 394-395, 476): Filter, expand (inspect evidence), edit selection, approve import, skip, back, retry source.
3. Current state in repo
Disposition: rework (frontend) + partial (backend). A trust-gate preview→commit flow EXISTS
in two places but neither delivers the categorized, per-item-confidence, per-item-selectable review
the screen requires. The existing surfaces are a thin preview list + commit-all, not a review gate.
3a. Onboarding ImportStep (the closest match to S16)
apps/web/src/components/os/overlays/OnboardingWizard.tsx— step index 3 is "memory-import" (STEP_NAMES:35). It callsadapter.harvestPreview(data, source)and storesresult.preview(:163-164), thenadapter.harvestCommit(data, source)on approve (:168-177), then auto-advances to the template step. There is no separate "Memory Review" step — preview and commit are folded into the single ImportStep.apps/web/src/components/os/overlays/onboarding/ImportStep.tsx— renders a flatimportPreview.slice(0,10)list (:125-155) with one "Import N items" button. No category tiles, no per-item Type/Source/Confidence columns, no per-row selection, no evidence expand, no source-error/low-confidence states. Just "preview found → commit all → Memories imported!".STEP_NAMES/dots are hardwired to 8 steps (:35, dots:472). Inserting a dedicated Review step shifts the step indices (template/persona/api-key/ready are4/5/6/7) — a refactor touch-point.
3b. MemoryApp HarvestTab (post-onboarding harvest surface)
apps/web/src/components/os/apps/memory/HarvestTab.tsx— the richer harvest UI: connected-source chips, Claude Code auto-detect, SSE progress, resume banner. ItsPreviewResultinterface (:28-33) is{ source, itemCount, types: Record<string,number>, preview: {id,title,type}[] }.typesgives a per-typecount map (the seed for category tiles) butpreviewis capped at 10 items, carries no confidence, and commit is all-or-nothing (no selection).- Reached today via
MemoryApp.tsx:272(<HarvestTab />, the "Harvest" tab).
3c. Backend preview/commit contract (what the UI can rely on)
packages/server/src/local/routes/harvest.ts:POST /api/harvest/preview(:221-236) returns{ source, itemCount, types: countByField(items,'type'), preview: items.slice(0,10).map(i => ({id,title,type,source})) }. No confidence field; first-10 only.POST /api/harvest/commit(:243+) parses with the adapter and writes every item as a raw frame:FrameStore.createIFrame('harvest', label+content, 'normal', 'import', ts)(:403-409). No selection input, no confidence, no per-item categorization beyond the adapter'stype.
adapter.harvestPreview/harvestCommit(apps/web/src/lib/adapter.ts:1684-1692) — both typedany, signature(data, source). NoselectedIds/approveparams exist.- The 4-pass
HarvestPipeline(classify→extract→synthesize w/confidence+ dedup/contradiction flags) EXISTS but is NOT called by the commit route (backend-map05c§3, §4, line 7, 110, 117).DistilledKnowledge.provenance.confidenceis produced only inside that unused pipeline. So the confidence + categorization data the mockup shows has no production producer today — this is the central backend gap (see §5).
Net: the trust-gate intent (preview before commit, nothing imports without consent) is partly honored; the categorized, confidence-scored, per-item-approvable review surface the screen specifies is not built.
4. Frontend work
Create a real Review surface usable from BOTH onboarding and the standing J08 queue.
Components to create
overlays/onboarding/MemoryReviewStep.tsx(NEW) — onboarding step 5. Replaces the inline preview block currently embedded inImportStep.tsx. Renders the full review layout.apps/web/src/components/os/apps/memory/MemoryReview.tsx(NEW, shared) — the reusable review panel (category tiles + tabbed table + right rail + footer actions). Both the onboarding step and a Memory-app "Review" surface mount this so there is ONE review implementation.components/os/apps/memory/review/sub-parts (small files per CLAUDE.md file-org rule):CategoryStatTiles.tsx,ReviewTable.tsx(Content/Type/Source/Confidence cols + row checkbox + expand-for-evidence),ImportSummaryRail.tsx(per-category counts + Top sources + Confidence guide legend),ReviewFooter.tsx(Back / Skip / Edit selections / Approve & import N).
Reuse targets (do not rebuild)
ContextMenu.tsx,components/ui/{table,tabs,checkbox,badge,input,scroll-area,skeleton}.tsx(shadcn set per frontend inventory §e) for the table/tabs/empty/loading states.ContextRail.tsx(overlays/ContextRail.tsx, exportsContextRailTarget) as the evidence/inspect pattern for "expand → inspect evidence" (J08) rather than inventing a new evidence panel.- HarvestTab's SSE progress wiring (
/api/harvest/progress, phases saving/cognifying/wiki-compile) for the "Approved → importing" state — lift the subscription into the shared panel. - Color semantics from Blueprint design system (line 485): green=healthy/high-confidence,
orange=attention/low-confidence, red=risk/error — map to existing Hive DS semantic tokens
(no
hive-950literals; tokens inwaggle-theme.css).
Props / state (shared MemoryReview)
interface ReviewItem {
id: string; title: string; content: string;
kind: MemoryKind; // mapped from ImportItemType (see §6)
source: ImportSourceType; // for the Source column + Top-sources rail
confidence?: number; // 0-100; undefined until backend produces it (see §5)
selected: boolean; // default true for high-confidence, false/uncertain otherwise
evidence?: string[]; // for the expand/inspect row
}
interface MemoryReviewProps {
mode: 'onboarding' | 'queue';
items: ReviewItem[]; loading: boolean; error?: string;
onApprove: (selectedIds: string[]) => Promise<void>; // → harvestCommit w/ selection
onSkip: () => void; onBack?: () => void;
onRetrySource?: (source: ImportSourceType) => void;
}
- Local state: per-category selection, search query, active category tab, expanded-row id.
selectedsemantics enforce the AC: low-confidence rows start unselected so nothing uncertain imports silently (J08).
Adapter / hook changes
- Extend
adapter.harvestCommitto accept an optional{ selectedIds }(orapprovedIds) param; type the preview response properly (dropany):HarvestPreview { source; itemCount; types: Record<MemoryKind, number>; items: ReviewItem[] }— note the preview must return all items (or paginate), notslice(0,10), for a real review (see §5). - NEW hook
useMemoryReview(source, data)(or fold into auseHarvesthook) owning preview fetch + selection state + commit; consumed by both mount points. - Onboarding
STEP_NAMES/dots/progressPctinOnboardingWizard.tsxmust add the Review step (8→9 steps OR split import/review and re-key 4-7). UpdatedisplayStep, dot array (:472), Back-button range (:444), and thegoToStep(4)auto-advances inhandleImportCommit/handleClaudeCodeHarvestto land on Review, not Template.
5. Backend work
PRD §16.5 Harvest endpoints
| PRD §16 endpoint | Status | Extend vs net-new / substrate |
|---|---|---|
POST /api/harvest/preview |
EXISTS (extend) | harvest.ts:221. Today returns types + first-10 preview with no confidence and no full item list. EXTEND to (a) return all items (or ?limit/offset paging) and (b) attach a per-item confidence + normalized kind. Substrate: UniversalImportItem (already carries type); confidence must come from a classifier (see below). No .mind migration for preview (in-memory parse). |
POST /api/harvest/commit |
EXISTS (extend) | harvest.ts:243. Today commits all parsed items. EXTEND body to accept { selectedIds?: string[] }; when present, filter items before the createIFrame loop (:382-409). Honors the trust-gate AC ("nothing imports without approval"). Substrate: writes to memory_frames in personal.mind via FrameStore.createIFrame — unchanged shape, just a filtered set. |
GET /api/harvest/sources |
EXISTS | harvest.ts (HarvestSourceStore). Powers the right-rail "Top sources" + connected-source chips. |
POST /api/harvest/sources/:id/sync |
PARTIAL | No per-source /sync route (backend-routes.md §16.5; grep-confirmed absent). Sync today = POST /api/harvest/commit. Add a thin /sources/:source/sync that resolves the registered source + re-runs commit. NOTE PRD path uses :id; current sources are keyed by :source name (DELETE/PATCH /api/harvest/sources/:source) — keep the name key or alias. Net-new thin route, no new substrate. |
Confidence + categorization (the real backend gap — implied addition to §16.5)
The mockup's Confidence column / Confidence guide / low-confidence queue (J08) and the 5 category tiles have no production producer:
memory_frameshas NOconfidencecolumn (substrate-types §c, line 137: confidence exists only onknowledge_relations.confidence). Frames are writtenimportance='normal', source='import'.- The classifier that yields
{categories, value, confidence}is the unusedHarvestPipeline(Pass 1 Classify Haiku + Pass 3 Synthesize →DistilledKnowledge.provenance.confidence), bypassed by the commit route (05c line 7). - Category counts beyond the adapter's raw
type(8ImportItemTypevalues) require a classify step; the adaptertypealone gives a coarse grouping but not the mockup's Memories/Decisions/Tasks/Artifacts/Projects taxonomy 1:1.
Decision needed (Open Q): to deliver real confidence, the refactor must either
(a) wire HarvestPipeline's classify/synthesize into a preview-time scoring pass (cost: Haiku/
Sonnet LLM calls per import — slow + paid; gated on a real embedder/key), or
(b) ship a cheap heuristic confidence at preview time (source-trust × adapter-type × dedup
signal) and reserve LLM scoring for an opt-in deep pass. Given onboarding latency budgets, (b) is
the pragmatic v1; (a) for the standing J08 queue.
.mind migration flag: if confidence becomes a queryable/filterable frame property (Filters in
the mockup; J08 "low-confidence review queue" off Home), add a nullable metadata TEXT DEFAULT '{}'
column to memory_frames (substrate-types §c line 156-164: the migration runner already does
idempotent ADD COLUMN on memory_frames; pattern at mind/db.ts:116-124) and store
{kind, confidence, sourceId, status} there, OR promote confidence REAL to a real column if it's
a primary filter axis. This is the only potential schema migration on this screen. Preview-only
confidence (not persisted) needs no migration.
Standing low-confidence queue (J08) backend
- "Home alert → Memory Review queue" needs a way to list already-imported low-confidence frames.
No route exists. Closest:
GET /api/memory/frames(memory.ts:188) + a confidence/status filter. This depends on confidence being persisted (above). Implied addition to §16.4 Memory, not §16.5.
6. Shared types needed (PRD §15 vs lib/types.ts)
MemoryKind(PRD §15.2): MISSING inapps/web/src/lib/types.ts(substrate-types §e). FEMemoryFrame.typeexists but mismatches PRD (event/insightvs PRDpreference/strategy/learning/goal). The review needs aMemoryKindunion AND a mapping from the harvestImportItemType(8 values: conversation/memory/instruction/preference/artifact/rule/decision/ document — 05c §1) to the review categories (Memories/Decisions/Tasks/Artifacts/Projects). That map is a new pure helper (lib/harvest-kind-map.ts).Confidence(PRD §15.2, 0-100): MISSING. Add the type; addconfidence?: numberto the review item shape (and laterMemoryFrameonce persisted).ReviewItem/HarvestPreviewresponse types: NEW (replace theanyonadapter.harvestPreview/harvestCommit). Mirror the server contract; co-locate or add tolib/types.ts.ImportSourceTypealready documented in 05c (24-value union) — import/re-declare for the Source column + Top-sources rail.
7. Dependencies (screens / phases first)
- Upstream (must precede): S15 Memory Import — supplies the
{data, source}(or connected source) that S16 reviews. TheharvestPreviewcall + source selection live there. - Shares substrate with: S-Memory Center (§12.4) — the persisted-frame edit/archive/merge +
the J08 low-confidence queue read from the same
memory_frames+ confidence field. Build the confidence-on-frames decision once and reuse. - Feeds: S-Home Cockpit (§12.1) — the "low-confidence review" Home alert (J08) deep-links into
this surface; needs
/api/home/*(separate gap) + the persisted-confidence read. - Onboarding flow (S-Onboarding): inserting the Review step re-keys
OnboardingWizardstep indices — coordinate with whoever owns the onboarding-flow gap card so step numbering is changed once. - Phase hint: core trust-gate (preview-with-selection + commit-selected + cheap heuristic confidence) is an early phase (it gates onboarding J01, a day-0 flow). The persisted-confidence column + LLM classify pass + standing J08 queue are a later phase (depend on the Memory Center confidence decision).
8. Effort
L. The reusable review panel + onboarding step re-keying + adapter/preview type-tightening +
commit selection are M on their own; the confidence/categorization producer (heuristic v1 now,
optional LLM-classify + possible memory_frames metadata migration later) plus the J08 standing
queue push it to L. It is NOT XL because no new data store is required — everything writes to the
existing memory_frames substrate via FrameStore, and the preview/commit routes already exist to
extend rather than build net-new.
9. Open questions
- Confidence source (blocking design): heuristic-at-preview (source-trust × type × dedup) vs
wiring the existing
HarvestPipelineclassify/synthesize for real LLM confidence? Latency/cost vs fidelity. Recommendation: heuristic for onboarding v1, LLM for the J08 queue. (§5) - Persist confidence? If "Filters" + J08 queue need to query confidence on already-imported
frames, we need the
memory_framesmetadata/confidencemigration. If review is preview-only (pre-commit), no migration. Which scope is v1? (§5) - Category taxonomy mapping: mockup shows Memories/Decisions/Tasks/Artifacts/Projects, but the
adapter emits 8
ImportItemTypes and PRD §15.2MemoryKindis a different set. Which is canonical, and what is the exactImportItemType → categorymap (esp. "Projects" — Claudeprojects[].docsland asartifactitems per 05c §2)? (§6) - Per-item edit: the footer "Edit selections" + interaction "edit selection" — is this just include/exclude (checkbox), or inline content/kind editing pre-commit? Pre-commit edit has no route today (frames don't exist yet); would need to mutate the in-memory item set before commit.
- Onboarding step count: split Import↔Review into two steps (8→9) or keep one screen with a
review sub-state? Affects
STEP_NAMES, dots, progress, and the "Step N" label already softened to avoid a fixed total (OnboardingWizard.tsx:456-467). - Source-error / retry-source state: S15 owns connect/parse; does S16 only display the partial state and offer "retry source" (re-invoking S15's connect), or own retry itself?