Skip to content

Memory Processing State — Feed Flag and UI Loading State

Plan Metadata

System Intent

  • What is being built: Surface the existing processing_status column (already written by ingest_window.py as "pending""complete" / "failed") through the feed API and render distinct visual states in the mobile app: semi-greyed-out for pending (processing in progress) and a red tint for failed (pipeline error).
  • Primary consumer(s): MemoryCard, MemoryRow, MemoryFeed, and the home screen (app/app/index.tsx).
  • Boundary: processing_status is already stored in worldmm_segments and maintained by the ingest pipeline. This plan only adds the read path: feed API returns a processing_status string, and the frontend renders state-specific overlays for pending and failed items.

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: MemoryFeedItem is defined in main/app/lib/api/memory/listMemories.ts. main/app/lib/api/memory/memoriesMock.ts has 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

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).