Skip to content

Wire engram admission gate into Rust hot path (persona::respond) so chat turns actually accumulate memory #1211

@joelteply

Description

@joelteply

airc-queue card

Coordinates work via the AIRC queue substrate (airc#562). Edit this card by commenting OR by running airc queue claim/airc queue release/airc queue heartbeat (later PRs).

{
  "kind": "airc-queue-card-v1",
  "id": "#1211",
  "owner": "claude-tab-1",
  "status": "merged",
  "evidence": "Adopted existing GitHub issue into airc queue.",
  "next_action": "Triage, claim, or close this adopted backlog card.",
  "last_heartbeat": "2026-05-14T19:34Z @ d8b506e75"
}

Close this issue when the work is done (status=merged/abandoned).

Original issue body

Pre-adoption body

Filed from #1195 finding (see comment for the full diagnosis).

The actual gap

The admission/engram thread (#1121 PR-1..5) shipped:

But: persona/response.rs::respond() — the actual hot path called by every chat turn via cognitionPersonaRespond — never invokes admission. grep -n 'admission' response.rs = 0 hits. So the admission gate is plumbed end-to-end but no chat turn ever reaches it. Personas accumulate zero memory.

Per Joel's "if not UI/UX it is rust" rule

Admission is hot-path cognition. It belongs in respond() (or an inline pre-step), not orchestrated from TS. The right architecture is:

// persona/response.rs
pub async fn respond(input: RespondInput) -> Result<PersonaResponse, String> {
    // 1. ADMISSION GATE — decide whether this turn's signal is memorable.
    //    Side effects: admitted engram → store, content_hash → dedup,
    //    AIRC event_id → replay-protection.
    let admission_decision = admission_runner.admit(
        &input.as_inbox_message_ref(),
        &mut input.trace,
    )?;

    // 2. If admitted, recall related engrams to enrich context for the
    //    response generation step (replaces / augments rag/build's
    //    current message-only context with engram-aware context).
    let recalled = if admitted_or_quarantined(&admission_decision) {
        admission_state.recall_recent(10)
    } else {
        Vec::new()
    };

    // 3. Continue existing respond() pipeline (analysis → score → assemble
    //    → inference → strip), with `recalled` available to prompt assembly.
    respond_inner(input, recalled).await
}

Required pieces

  1. RespondInputInboxMessage conversion. Today RespondInput carries Signal+PersonaContext from the IPC. Need a to_inbox_message() projection so the admission runner can score it.
  2. recalled: Vec<Engram> plumbed into prompt_assembly so admitted memory becomes part of the system / context section of the inference prompt.
  3. admission_state accessible from respond() — currently lives on ModuleState.personas[uuid].admission. Needs to be passed in (or respond() becomes a method on PersonaCognitionState).
  4. Integration test: send "my favorite color is teal" → next turn from same persona should reference teal via the recall path.

Out of scope

Why this beats the recipe-wiring framing

The recipe approach assumes a walker exists OR will exist. Today neither is true. The Rust hot-path approach:

  • works the moment it merges (no walker dependency)
  • runs admission on EVERY chat turn (no opt-in per recipe)
  • single source of truth (admission decision lives next to the response decision; can't drift)
  • matches Joel's "native-truth, thin-SDK" architectural rule

Validation

  • cargo test --lib --features metal passes (existing admission tests + new respond() integration test).
  • Live smoke: chat probe (./jtag collaboration/chat/send) → after 2-3 turns, ./jtag cognition/recall-engrams --personaId=<helper-ai-uuid> returns non-empty.
  • Replay tests stay green (no behavior change for personas that don't use engram recall).

Filed by claude-tab-1 from #1195 PR-1 work. Refs #1121.

Status log

  • 2026-05-14T20:33Z — airc-8a5e-bc43 -> status=merged

  • 2026-05-14T19:49Z — claude-tab-1 -> status=review

  • 2026-05-14T19:34Z — claude-tab-1 -> status=in-progress

  • 2026-05-14T19:34Z — claim by claude-tab-1 -> status=in-progress

  • 2026-05-14T17:45Z — claude-tab-1 -> status=review

  • 2026-05-14T17:34Z — claude-tab-1 -> status=in-progress

  • 2026-05-14T17:34Z — claim by claude-tab-1 -> status=in-progress

Metadata

Metadata

Assignees

No one assigned

    Labels

    airc-queueAIRC-backed agent work queue card

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions