Memory Processing State — Feed Flag and UI Loading State
Plan Metadata
- Plan type:
plan - Parent plan: N/A
- Depends on:
memory-fetch-display.md - Status:
documentation
System Intent
- What is being built: Surface the existing
processing_statuscolumn (already written byingest_window.pyas"pending"→"complete"/"failed") through the feed API and render distinct visual states in the mobile app: semi-greyed-out forpending(processing in progress) and a red tint forfailed(pipeline error). - Primary consumer(s):
MemoryCard,MemoryRow,MemoryFeed, and the home screen (app/app/index.tsx). - Boundary:
processing_statusis already stored inworldmm_segmentsand maintained by the ingest pipeline. This plan only adds the read path: feed API returns aprocessing_statusstring, and the frontend renders state-specific overlays forpendingandfaileditems.
Stage Gate Tracker
- [x] Stage 1 Mermaid approved
- [x] Stage 2 I/O contracts approved
- [x] Stage 3 pseudocode/technical details approved or skipped
1. Mermaid Diagram
flowchart TD
subgraph PIPELINE["WorldMM Ingest Pipeline — unchanged"]
INGEST["ingest_window.py\nworldmm/pipeline/ingest_window.py"]:::unchanged
end
subgraph DB["PostgreSQL"]
SEG[("worldmm_segments\nprocessing_status: pending | complete | failed\nworldmm_orm.py — shared/orm/worldmm_orm.py")]:::unchanged
end
subgraph FEED_API["Feed Lambda"]
FEED["feed app.py\napi/memories/feed/app.py"]:::unchanged
end
subgraph APP["Mobile App"]
LIST["listMemories + MemoryFeedItem\nlib/api/memory/listMemories.ts"]:::unchanged
MOCK["memoriesMock\nlib/api/memory/memoriesMock.ts"]:::deleted
MCARD["MemoryCard\ncomponents/memory/MemoryCard.tsx"]:::unchanged
MROW["MemoryRow\ncomponents/memory/MemoryRow.tsx"]:::unchanged
MODAL["MemoryViewerModal\ncomponents/memory/memory-viewer-modal.tsx"]:::unchanged
end
INGEST -->|"processing_status = pending on stub create\nprocessing_status = complete or failed on finish"| SEG
FEED -->|"SELECT worldmm_segments WHERE user_id"| SEG
SEG -->|"processing_status per row"| FEED
FEED -->|"MemoryFeedItem + processing_status: pending | complete | failed"| LIST
LIST -->|"processing_status forwarded to components"| MCARD
LIST -->|"processing_status forwarded to components"| MROW
LIST -->|"processing_status forwarded to modal"| MODAL
classDef unchanged fill:#d3d3d3,stroke:#666,stroke-width:1px
classDef updated fill:#ffe58a,stroke:#666,stroke-width:1px
classDef created fill:#a8e6a3,stroke:#666,stroke-width:1px ONCE YOU GET APPROVAL FROM THE DEVELOPER, DELETE THIS LINE AND UPDATE THE STAGE GATE TRACKER
2. Black-Box Inputs and Outputs
Global Types
Type ownership:
MemoryFeedItemis defined inmain/app/lib/api/memory/listMemories.ts.main/app/lib/api/memory/memoriesMock.tshas been deleted — the type and mock data it held are no longer needed.
MemoryFeedItem {
id: string (UUID — worldmm_segments PK)
time: string (ISO 8601 — segment start_time)
type: "text" | "audio" | "visual" (derived from segment content; unchanged)
thumbnail?: string | null (presigned S3 URL; absent if no frame; unchanged)
featured?: boolean (always false currently; unchanged)
processing_status: "pending" | "complete" | "failed" (NEW — passed through from worldmm_segments)
}
Pass-through rule: processing_status is forwarded verbatim from worldmm_segments.processing_status. No server-side mapping — the frontend owns the rendering decision per status value.
Flow: listMemories — paginated memory feed
- Test files:
main/server/tests/integration/test_memories_feed_pagination.py - Core files:
main/server/api/memories/feed/app.py,main/app/lib/api/memory/listMemories.ts
Type Definitions
FeedRequest {
cursor?: string | null (offset; null or omit for first page)
limit?: number (default 20, max 50)
}
FeedResponse {
memories: MemoryFeedItem[]
next_cursor: string | null
}
Paths
| path-name | input | output/expected state change | path-type | notes | updated |
|---|---|---|---|---|---|
feed.processing-pending | segment row with processing_status="pending" | MemoryFeedItem with processing_status: "pending" | happy path | thumbnail may still be present if s3_frames_key was set at stub creation | |
feed.processing-failed | segment row with processing_status="failed" | MemoryFeedItem with processing_status: "failed" | subpath | distinct from pending — frontend renders red tint | |
feed.complete | segment row with processing_status="complete" | MemoryFeedItem with processing_status: "complete" | happy path | normal rendering; field newly included | |
feed.unauthenticated | no JWT | 401 | error | unchanged | |
feed.user-isolation | valid JWT user A | never returns segments owned by user B | security | unchanged |
Flow: renderProcessingState — frontend visual loading state
- Test files:
main/app/__tests__/memory-viewer-modal.test.tsx,main/app/__tests__/memory-feed-screen.test.tsx - Core files:
main/app/components/memory/MemoryCard.tsx,main/app/components/memory/MemoryRow.tsx,main/app/components/memory/memory-viewer-modal.tsx
Type Definitions
MemoryCardProps {
memory: MemoryFeedItem (includes processing_status)
onPress?: () => void
}
MemoryRowProps {
memory: MemoryFeedItem (includes processing_status)
onPress?: () => void
}
Paths
| path-name | input | output/expected state change | path-type | notes | updated |
|---|---|---|---|---|---|
render.card-pending | MemoryFeedItem with processing_status: "pending", type: "visual" | MemoryCard renders thumbnail with semi-transparent grey overlay (opacity ~0.4) | happy path | indicates processing in progress; thumbnail shown underneath if present | |
render.card-failed | MemoryFeedItem with processing_status: "failed", type: "visual" | MemoryCard renders thumbnail with semi-transparent red tint overlay | happy path | indicates pipeline error; thumbnail shown underneath if present | |
render.row-pending | MemoryFeedItem with processing_status: "pending", type: "audio" or "text" | MemoryRow renders at reduced opacity (~0.5) | happy path | consistent grey treatment for non-visual types | |
render.row-failed | MemoryFeedItem with processing_status: "failed", type: "audio" or "text" | MemoryRow renders with red tint | happy path | red tint consistent with card failed treatment | |
render.modal-pending | viewer opened on item with processing_status: "pending" | modal image shown at reduced opacity with grey overlay | subpath | user may tap into a pending memory | |
render.modal-failed | viewer opened on item with processing_status: "failed" | modal image shown with red tint overlay | subpath | user may tap into a failed memory | |
render.card-complete | MemoryFeedItem with processing_status: "complete" | MemoryCard renders normally, no overlay | happy path | unchanged rendering path | |
render.row-complete | MemoryFeedItem with processing_status: "complete" | MemoryRow renders normally, full opacity | happy path | unchanged rendering path |
3. Pseudocode / Technical Details for Critical Flows (Optional)
ONCE YOU GET APPROVAL FROM THE DEVELOPER, DELETE THIS LINE AND UPDATE THE STAGE GATE TRACKER
4. Handoff to Related Plan Reconciliation
After all stages are approved, apply .agent/skills/reconcile-plans/SKILL.md to propagate contract updates to memory-fetch-display.md (which owns the MemoryFeedItem type contract).