17 KiB
Gap Card — S04 Memory Center
Screen S04 of the Waggle OS UX Refactor. Execution model: in-place incremental refactor of
apps/web+ targeted backend extension over the existing.mindsubstrate. Mockup is directional; PRD §12.4 + §16.4 acceptance criteria win. Sources: PRDdocs/Waggle_OS_UX_Refactor_Master_Handoff_Package/Waggle_OS_UX_Refactor_PRD.md(§12.4 lines 484-517, §16.4 lines 1086-1094, §15.4 lines 988-1013, §20.2 line 1276); backend-mapsections/03b-api-memory.md,sections/05b-subsystem-memory.md; inventories underdocs/ux-refactor/_inventory/.
1. Screen & purpose
Make memory visible, trustworthy, searchable, and editable (PRD §12.4). Every memory item must answer: what do I know, why do I know it, where did it come from, how confident am I, can I edit it? (PRD line 517).
Mockup (screen_04_memory_center.png, directional) shows a 3-pane layout:
- Left rail — search box, type/source/confidence/workspace/tag/date filter facets, scope tabs.
- Center list — memory cards (title, type icon, snippet, confidence/importance, source chip, date).
- Right detail panel — selected memory: content, type/source/evidence, confidence ring/score, related memories, connected-graph mini-view, source-evidence chips, and an actions row (edit / merge / archive / delete / share / add-to-workspace). A right-most column in the mockup shows aggregate stats (frame count, distribution donut, top entities, recent activity).
This is the Work-layer "visible memory" pillar (PRD §1, §6 principle 2, §10.2).
2. Required states (PRD/Blueprint)
Tabs (PRD §12.4): Active · Workspace · Team · Sources · Graph · Trash.
Filters (PRD §12.4): type, source, confidence, importance, workspace, tag, date.
Memory detail view fields (PRD §12.4 line 500): content, type, source, evidence, confidence, relevance, last used, tags, timeline, connected graph.
Actions (PRD §12.4 line 502): edit, merge, archive, delete, share, add to workspace/team; show related memories + source evidence.
Screen states (PRD §12.4 lines 504-513 + global §14.1/§14.4): Empty memory · Importing · Consolidating · Active · Low confidence · Conflict · Deprecated · Source unavailable — plus the global set Loading / Populated / Error / Offline-local-only / Permission-denied / Partial-data / Approval-required, and the memory lifecycle states Raw/Imported/Working/ Consolidated/Active/Low-confidence/Conflicting/Deprecated/Archived/Deleted-tombstoned (§14.4).
Acceptance (PRD line 517): every memory exposes content + source + provenance + confidence
- edit/delete. Privacy (§18.2): memory source and scope must be visible; user must be able to archive/delete; team sharing requires explicit scope.
Blueprint note:
_blueprint_extracted.txtpage 31 ("Screen 4 - Memory Center") is an image-only heading — no extra written spec beyond PRD. Cross-refs confirm the rework intent: line 571 "TurnMemoryApp.tsxinto Memory Center with source/confidence/ evidence/edit actions", line 296 "Visible memory with provenance and [confidence]".
3. Current state in repo
Disposition: REWORK (matches PRD §20.2 line 1276: MemoryApp.tsx -> Memory Center).
Substantial reuse of substrate + hook; the screen's tab axis, detail panel, and trust
surfacing are rebuilt.
Primary component — apps/web/src/components/os/apps/MemoryApp.tsx (343 LOC).
Today it is a 6-tab hub on a different axis than the PRD:
MEMORY_TABS(line 46):timeline | graph | harvest | weaver | wiki | evolution— NOT the PRD'sActive/Workspace/Team/Sources/Graph/Trash. Only Graph overlaps 1:1.- Left sidebar (line 119): search input (
onSearchChange), a type-filter chip set (FRAME_TYPES, line 21) + a min-importance range slider; flat chronological frame list. - Detail pane (line 281): renders type icon, title,
typechip,importance: N/5, timestamp, markdown content, and a rawmetadataJSON dump (line 310). Edit button is a no-op (line 289 — no handler); only Delete is wired. No source, no confidence, no evidence, no relevance, no related-memories, no tags, no timeline, no merge/archive/share. readFrameProvenanceTool()(line 32) already readsmetadata.tool|sourceTool|sourceand renders a small amber provenance badge (line 202) — the only trust signal present today.ImportReminderBanner(line 236) handles the "you have pending imports" nudge.
Subcomponents — apps/web/src/components/os/apps/memory/ (6 files):
KnowledgeGraphViewer.tsx→ PRD Graph tab (keep-promote, reuse as-is).HarvestTab.tsx→ maps to Sources tab inputs (keep; Sources tab wraps/extends it).WeaverPanel.tsx,WikiTab.tsx,EvolutionTab.tsx,ImportReminderBanner.tsx→ these are out of the PRD Memory-Center tab set. Per inventoryfrontend.md(f), Weaver/Wiki/ Evolution belong to the Intelligence layer (traces/distillation). The rework should move them off the Memory-Center tab bar (relocate to their IA home or keep behind a secondary surface) rather than delete — flag as IA cleanup, not in-scope deletion.- Grep confirmed: no file under
memory/renders confidence/evidence/provenance beyond the inline badge inMemoryApp.tsx. The trust UI is greenfield.
Hook — apps/web/src/hooks/useMemory.ts (81 LOC). Provides frames, selectedFrame,
filters{types,minImportance,searchQuery}, addFrame/editFrame/deleteFrame/incrementAccess/ refresh, stats{total,filtered,entities,relations}. Calls adapter.getMemoryFrames,
searchMemory, getMemoryStats, addMemoryFrame, updateMemoryFrame, deleteMemoryFrame,
incrementFrameAccess. Reuse and extend (add merge/archive, scope/source/confidence/tag
filters, single-frame fetch).
Wiring — Desktop.tsx: const memory = useMemory(activeWorkspaceId) (line 107);
<MemoryApp .../> rendered for appId memory (lines 309-316) with frames/selectedFrame/ searchQuery/stats/typeFilters/minImportance + KG props (knowledgeGraph, kgScope). The
appId memory already exists in AppId (dock-tiers) — no new route needed (single-route
windowed desktop; inventory frontend.md §b).
Frontend type — apps/web/src/lib/types.ts:118-127 MemoryFrame: id,type,title,content, importance:number,timestamp,workspaceId,metadata?. Note inventory finding: this FE shape does
not match what /api/memory/frames returns (server normalizeFrame emits source, source_mind, frameType, accessCount, score, …, memory.ts:25-58) — a real FE/BE contract
mismatch to reconcile in this rework.
4. Frontend work
Rework MemoryApp.tsx → Memory Center (keep file path per §20.2; do not create a parallel app).
Components to create/rework (small files, per house rules):
MemoryApp.tsx(rework shell) — replace the 6-tab bar with PRD tabsActive | Workspace | Team | Sources | Graph | Trash. Keep the 3-pane layout (rail / list / detail). State:activeTab,filters,selectedFrameId,view.memory/MemoryFilterRail.tsx(new) — facet filters: type, source, confidence range, importance, workspace, tag, date. DrivesuseMemory().setFilters.memory/MemoryList.tsx(new) — extract the card list out ofMemoryApp; each card shows title, type icon, snippet, confidence badge, source chip, date. Loading/empty/error states.memory/MemoryDetailPanel.tsx(new) — the PRD detail view: content + type + source +evidence[]chips +ConfidenceBadge+ relevance + last-used + tags + mini-timeline + connected-graph snippet + related-memories list. Actions row: edit, merge, archive, delete, share, add-to-workspace/team. Reuse design-system primitives from PRD §19.1 (Confidence badges,Source/evidence chips,Status badges,Timeline,Detail drawer,Approval promptfor share/delete).memory/MemoryEditDialog.tsx(new) — wire the currently-dead Edit button (MemoryApp.tsx:289) touseMemory().editFrame.memory/MemoryMergeDialog.tsx(new) — select 2+ frames → call merge adapter method.- Reuse as-is:
KnowledgeGraphViewer.tsx(Graph tab),ContextMenu.tsx,HintTooltip,renderSimpleMarkdown. Relocate off this tab bar:WeaverPanel,WikiTab,EvolutionTab,HarvestTab(Harvest folds into the new Sources tab). overlays/ContextRail.tsxis already the right-side full-context rail (onContextRailprop,MemoryApp.tsx:75,183) — keep the integration.
Hook/adapter work (useMemory.ts + lib/adapter.ts):
- Extend
MemoryFiltersto{ types, sources, minConfidence, minImportance, workspaceId, tags, dateFrom, dateTo, scope, searchQuery }; filter client-side first, push server-side where the route supports it (/api/memory/searchalready acceptssince/until/workspace/scope,memory.ts:117-120). - New adapter methods (thin wrappers; adapter is the single sidecar contract surface — inventory
frontend.md(c)):getMemoryFrame(id),archiveMemoryFrame(id),mergeMemoryFrames(ids[]),shareMemoryFrame(id, scope)(Team tab). Team tab reuses existingsearchTeamMemory(adapter.ts:489). - Reconcile
MemoryFrameFE type vs servernormalizeFrameoutput (addsource,sourceMind,confidence,tags,evidence,status,relatedMemoryIds— see §6).
States to implement (all PRD-required): Loading / Empty / Populated / Error / Offline /
Permission-denied / Importing / Consolidating / Low-confidence (badge) / Conflict (badge +
conflictNote from CombinedRetrieval, backend-map 05b §8) / Deprecated / Source-unavailable /
Trash.
5. Backend work (PRD §16.4 endpoints)
Status per inventory backend-routes.md Part 2 §16.4, re-verified against
packages/server/src/local/routes/memory.ts + knowledge.ts. Substrate = memory_frames
(+_fts/_vec) and knowledge_entities/relations in packages/hive-mind-core/src/mind/.
| PRD §16.4 endpoint | Status | Action — EXTEND existing vs NET-NEW · substrate |
|---|---|---|
GET /api/memory |
PARTIAL | EXTEND: alias/accept on existing GET /api/memory/frames (memory.ts:188). No new substrate. |
GET /api/memory/:id |
MISSING | NET-NEW thin route reading FrameStore.getById(id) (backend-map 05b §2). memory_frames. No migration. |
POST /api/memory |
PARTIAL | EXTEND: alias on POST /api/memory/frames (memory.ts:237). |
PATCH /api/memory/:id |
PARTIAL | EXTEND PUT /api/memory/frames/:id (memory.ts:448) to accept PATCH + bare :id. FrameStore.update. |
POST /api/memory/:id/archive |
MISSING | NET-NEW. Model archive as FrameStore.update(id, importance:'deprecated') (no hard delete) OR add status in the new metadata column (§6). memory_frames. |
DELETE /api/memory/:id |
PARTIAL | EXTEND: alias bare :id over DELETE /api/memory/frames/:id (memory.ts:551, → FrameStore.delete). |
POST /api/memory/merge |
MISSING | NET-NEW. Read N frames, synthesize merged content, write one frame, archive/delete the originals. Reuse FrameStore + dedup (findDuplicate, 05b §2). memory_frames. |
GET /api/memory/graph |
EXISTS | knowledge.ts GET /api/memory/graph?scope= — Graph tab. No work. |
Adjacent reuse (no new endpoint): Team tab → existing GET /api/team/memory/search
(team.ts, Tier: TEAMS, inventory backend-routes 1.8); Sources tab → existing
GET /api/harvest/sources (harvest.ts); stats column → existing GET /api/memory/stats
(memory.ts:391); conflict/relevance signals available from CombinedRetrieval
(backend-map 05b §8 hasConflict/conflictNote, finalScore relevance).
.MIND MIGRATION FLAG (one, low-risk). To back confidence / provenance-id / source-url /
tags / evidence / kind / title / status / relatedMemoryIds, memory_frames has NO metadata
column today (substrate-types.md (c): unlike awareness.metadata etc.). The migration runner
already does idempotent additive ADD COLUMN (precedent: it added source, mind/db.ts:116-124).
Recommended: ONE additive migration adding nullable
metadata TEXT NOT NULL DEFAULT '{}' to memory_frames, storing
{kind,title,scope,sourceId,sourceUrl,confidence,tags,evidence,relatedMemoryIds,status} as JSON.
This avoids touching the FTS5/vec0 virtual tables and the IPB scoring path. If confidence
becomes a primary filter/sort axis (PRD "filter by confidence" / "low-confidence surfaced"),
promote confidence REAL to a real indexable column in a later migration (same ADD-COLUMN
pattern). PRD §15.4 line 1013 explicitly endorses metadata-first.
Latent-bug flag (not session-induced, surfaced by substrate-types.md (d)):
AuditRiskLevelTS includes'critical'but the DDL CHECK allows onlylow/medium/high— irrelevant to S04 but the same install-audit store backs Sources-tab provenance if surfaced; note for the plan.
6. Shared types needed (PRD §15 vs lib/types.ts)
PRD §15.2 unions — none exist in apps/web/src/lib/types.ts (substrate-types.md (e)):
- Add
MemoryKind = 'fact'|'decision'|'task'|'preference'|'strategy'|'learning'|'goal'|'entity'(PRD line 949). CurrentMemoryFrame.type(types.ts:120) usesfact/event/insight/decision/ task/entity— OVERLAPS but mismatched (event/insightvs PRDpreference/strategy/learning/ goal). Reconcile. - Add
Scope = 'personal'|'workspace'|'team'|'organization'(line 945) — drives the Active/ Workspace/Team tab partition. Today scope is IMPLICIT (which.mindfile; surfaced as_mindtag,memory.ts:34). - Add
Confidence = number(0-100, line 946).
Extend MemoryFrame (PRD §15.4, lines 990-1013) toward: kind, title, content, scope, workspaceId, teamId, source, sourceId, sourceUrl, confidence, importance, evidence[], tags[], relatedMemoryIds[], relatedArtifactIds[], createdAt, updatedAt, lastAccessedAt, status.
relatedArtifactIds[] stays deferred (no Artifact entity exists yet — that's S05;
substrate-types.md (e)). Also fix the FE-type ↔ normalizeFrame mismatch noted in §3/§4.
7. Dependencies (screens/phases first)
- Phase placement: PRD §8 Phase 2 / Sprint 4 (Memory + Artifacts). Depends on Phase 0 (shared frontend types + AppShell/IA freeze — the §15.2 unions live there) and on the workspace-state/context contract from Phase 1.
- Workspace scope (
scope/workspaceId) presupposes the S01/S02 workspace-type-and-status fields (WorkspaceConfigV2, substrate-types.md (a)) for the Workspace/Team partition; usable with the implicit_mindscope before that lands, so soft dependency only. - Team tab depends on TEAMS tier + the team substrate (S10 Team Workspace); gate behind
useFeatureGate/tier and degrade to a "Teams feature" empty state otherwise. - Sources tab reuses Harvest (already shipped); the broader Memory Import onboarding (S15/S16) is independent.
- No dependency on S05 Artifacts for v1 (defer
relatedArtifactIds). - Open question O3 (PRD line 1418): Graph view in v1 or later — Graph already works, so keep.
8. Effort: L
Frontend is a multi-pane rework with a brand-new trust/detail surface (confidence, evidence,
related, merge, archive, share) replacing a thin detail pane, plus 4-5 new subcomponents and a
hook/adapter/type reconciliation. Backend is mostly EXTEND/alias over existing memory routes
(7 of 8 endpoints), but the trust fields require one additive .mind migration + a real
merge endpoint + a :id read + an archive path — net-new logic, low schema risk. The single
migration and the FE/BE MemoryFrame contract reconciliation push this past M into L.
9. Open questions
- Confidence source.
memory_frameshas no confidence today;knowledge_relations.confidenceexists (edges only, schema.ts:93). Do we (a) store confidence in the newmetadataJSON, (b) promote to aREALcolumn now for indexable low-confidence filtering, or (c) derive a proxy fromsourcetrust-class +importanceuntil real confidence is computed? (PRD §12.4 wants "filter by confidence" + "low-confidence surfaced for review".) - Conflict detection surfacing.
CombinedRetrieval.detectConflict(05b §8) yieldshasConflict/conflictNoteat recall time, not as a stored per-frame state. Is the PRD "Conflict" state (§14.4) a live recall-time signal or a persisted frame status? - Archive vs deprecate vs tombstone. PRD §14.4 distinguishes Deprecated / Archived /
Deleted-tombstoned.
importance:'deprecated'exists; is "archive" a distinct status (needs themetadata.statusfield) or an alias of deprecate? Delete = hardFrameStore.deleteor tombstone? (PRD Open Question O8, line 1423.) - Merge semantics. Does
POST /api/memory/mergeLLM-synthesize a combined frame, or just concatenate + re-cognify? What happens to the originals (archive vs hard delete)? - Tab-relocation scope. Confirm Weaver/Wiki/Evolution move OUT of the Memory-Center tab bar to their Intelligence-layer home (frontend.md (f)) is in-scope for S04, or deferred to the IA pass so S04 only adds the new tabs and leaves the legacy ones temporarily.
MemoryKindreconciliation. Drop FEevent/insightand add PRDpreference/strategy/ learning/goal? This changes existing frame rendering + the type-filter chips.