This commit is contained in:
278
docs/ux-refactor/gap-cards/S16-memory-review.md
Normal file
278
docs/ux-refactor/gap-cards/S16-memory-review.md
Normal file
@@ -0,0 +1,278 @@
|
||||
# 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`)
|
||||
```ts
|
||||
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 `ImportItemType`s 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?
|
||||
Reference in New Issue
Block a user