Skip to content

[P0-3] Pending-nudges queue: pending_nudges table + conversation-loop poll point + SDK nudges.enqueue #37

@justrach

Description

@justrach

Parent: #34
Priority: P0 (substrate — graff-memd injects memory/skill review prompts via this)
Branch base: release/0.1.53

Why

graff-memd needs to inject system messages into an active conversation (e.g. "review whether this turn warrants a skill update"). Hermes does this inline because it's a single Python process; we need a queue because sidecars are out-of-process.

Scope

Rust side

  • New table pending_nudges: (id, conversation_id, role, content, created_at, consumed_at NULL).
  • NudgeRepo::enqueue(conversation_id, role, content), next_unconsumed(conversation_id), mark_consumed(id).
  • Poll point in the conversation loop (forge_app) — at the start of each user turn, drain unconsumed nudges and prepend them as system messages before the LLM call. Mark consumed after the LLM call returns.

SDK side

  • graff.nudges.enqueue(conversationId, message)message: { role: "system" | "user_visible" | "user_hidden"; content: string }.
  • graff.nudges.list(conversationId) for inspection.

Acceptance

  • Enqueue → next user turn includes the nudge → consumed flag flips
  • Multiple queued nudges drain in FIFO order in a single turn
  • Nudges respect role: user_hidden injected as system, never shown in TUI

Metadata

Metadata

Assignees

No one assigned

    Labels

    severity: highSignificant impact; core functionality is impaired.type: featureBrand new functionality, features, pages, workflows, endpoints, etc.work: complexThe situation is complex, emergent practices used.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions