Files
waggle-os/docs/ux-refactor/gap-cards/S16-memory-review.md
Oleg Maslov 0c3e2ead3b
Some checks failed
Installer Smoke / installer-smoke (push) Has been cancelled
moving
2026-09-02 10:10:29 +02:00

18 KiB
Raw Permalink Blame History

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:
    1. Onboarding (J01 First-time setup): … → Memory Import → Memory Review → Workspace Creation.
    2. Standing low-confidence queue (J08): Home alert → Memory Review queue → inspect evidence → approve/edit/reject so "uncertain memory does not silently influence work."
  • 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 calls adapter.harvestPreview(data, source) and stores result.preview (:163-164), then adapter.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 flat importPreview.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 are 4/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. Its PreviewResult interface (:28-33) is { source, itemCount, types: Record<string,number>, preview: {id,title,type}[] }. types gives a per-type count map (the seed for category tiles) but preview is 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's type.
  • adapter.harvestPreview/harvestCommit (apps/web/src/lib/adapter.ts:1684-1692) — both typed any, signature (data, source). No selectedIds/approve params exist.
  • The 4-pass HarvestPipeline (classify→extract→synthesize w/ confidence + dedup/contradiction flags) EXISTS but is NOT called by the commit route (backend-map 05c §3, §4, line 7, 110, 117). DistilledKnowledge.provenance.confidence is 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 in ImportStep.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, exports ContextRailTarget) 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-950 literals; tokens in waggle-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.
  • selected semantics enforce the AC: low-confidence rows start unselected so nothing uncertain imports silently (J08).

Adapter / hook changes

  • Extend adapter.harvestCommit to accept an optional { selectedIds } (or approvedIds) param; type the preview response properly (drop any): HarvestPreview { source; itemCount; types: Record<MemoryKind, number>; items: ReviewItem[] } — note the preview must return all items (or paginate), not slice(0,10), for a real review (see §5).
  • NEW hook useMemoryReview(source, data) (or fold into a useHarvest hook) owning preview fetch + selection state + commit; consumed by both mount points.
  • Onboarding STEP_NAMES/dots/progressPct in OnboardingWizard.tsx must add the Review step (8→9 steps OR split import/review and re-key 4-7). Update displayStep, dot array (:472), Back-button range (:444), and the goToStep(4) auto-advances in handleImportCommit/ handleClaudeCodeHarvest to 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_frames has NO confidence column (substrate-types §c, line 137: confidence exists only on knowledge_relations.confidence). Frames are written importance='normal', source='import'.
  • The classifier that yields {categories, value, confidence} is the unused HarvestPipeline (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 (8 ImportItemType values) require a classify step; the adapter type alone 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 in apps/web/src/lib/types.ts (substrate-types §e). FE MemoryFrame.type exists but mismatches PRD (event/insight vs PRD preference/strategy/ learning/goal). The review needs a MemoryKind union AND a mapping from the harvest ImportItemType (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; add confidence?: number to the review item shape (and later MemoryFrame once persisted).
  • ReviewItem / HarvestPreview response types: NEW (replace the any on adapter.harvestPreview/harvestCommit). Mirror the server contract; co-locate or add to lib/types.ts.
  • ImportSourceType already 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. The harvestPreview call + 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 OnboardingWizard step 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

  1. Confidence source (blocking design): heuristic-at-preview (source-trust × type × dedup) vs wiring the existing HarvestPipeline classify/synthesize for real LLM confidence? Latency/cost vs fidelity. Recommendation: heuristic for onboarding v1, LLM for the J08 queue. (§5)
  2. Persist confidence? If "Filters" + J08 queue need to query confidence on already-imported frames, we need the memory_frames metadata/confidence migration. If review is preview-only (pre-commit), no migration. Which scope is v1? (§5)
  3. Category taxonomy mapping: mockup shows Memories/Decisions/Tasks/Artifacts/Projects, but the adapter emits 8 ImportItemTypes and PRD §15.2 MemoryKind is a different set. Which is canonical, and what is the exact ImportItemType → category map (esp. "Projects" — Claude projects[].docs land as artifact items per 05c §2)? (§6)
  4. 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.
  5. 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).
  6. 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?