Skip to content

feat(persona,LaneD): response_prompt() lazy output on PersonaTurnFrame#1400

Merged
joelteply merged 1 commit into
canaryfrom
feat/lane-d-response-prompt-lazy-output
May 18, 2026
Merged

feat(persona,LaneD): response_prompt() lazy output on PersonaTurnFrame#1400
joelteply merged 1 commit into
canaryfrom
feat/lane-d-response-prompt-lazy-output

Conversation

@joelteply
Copy link
Copy Markdown
Contributor

Summary

Lane D advancement. Adds the chat-style prompt lazy output the inference engine consumes. Closes the chain from inbox event → turn frame → ready-to-infer prompt, fully in Rust.

Pure Rust, zero TS.

What lands

  • ResponsePrompt struct: persona_id, room_id, system_prompt (Option; caller fills from IdentityState), messages (Vec), trigger_message_id
  • PromptRole enum: System / User / Assistant — chat-completion taxonomy
  • PromptMessage { role, content } — one turn in the prompt
  • PersonaTurnFrame::response_prompt() — fourth lazy output alongside consolidated_inbox + rag_seed + replay_record

Design

  • Every inbox message becomes a User-role PromptMessage in chronological order. The persona's identity (System role) is filled in by the caller from IdentityState (not loaded into the turn frame today; future PR may add lazily).
  • Per Joel's "Rust owns behavior" + "no TS shimming Rust outputs": the substrate owns the prompt-build path so TS PRG doesn't wrap a raw transcript into a model-specific prompt format.
  • Wire shape: camelCase fields (systemPrompt, triggerMessageId) + lowercase role enum (system/user/assistant) — matches the de-facto chat-completion JSON.
  • Returns None for empty frames (same contract as consolidated_inbox + rag_seed — empty inbox = no turn to plan).

This is the lazy output that PR-4 inference-llm's (#1395) InferenceRequest.prompt_text expects. A follow-up PR will add the turn-execute command chaining drain-turn-frameresponse_promptinference/llm/request for the full persona-turn-in-one-Rust-call.

Test plan

  • cargo test --lib --features metal,accelerate persona::turn_frame — 9/9 pass (5 new + 4 existing):
    • response_prompt_returns_none_for_empty_frame
    • response_prompt_carries_one_user_message_per_inbox_message
    • response_prompt_system_prompt_is_none_pr1 (pins the IdentityState separation)
    • response_prompt_trigger_matches_latest_message_id
    • response_prompt_round_trips_through_serde (wire stability)
  • No regressions across other 2973 lib tests
  • Pre-push gate clean

Stack

🤖 Generated with Claude Code

Lane D: adds the chat-style prompt lazy output the inference engine
consumes. Closes the chain from inbox event → turn frame → ready-to-
infer prompt, fully in Rust.

What lands

- ResponsePrompt struct: persona_id, room_id, system_prompt
  (Option<String>; caller fills from IdentityState), messages
  (Vec<PromptMessage>), trigger_message_id
- PromptRole enum: System / User / Assistant — chat-completion
  taxonomy
- PromptMessage { role, content } — one turn in the prompt
- PersonaTurnFrame::response_prompt() — fourth lazy output
  alongside consolidated_inbox + rag_seed + replay_record

Design

- Every inbox message becomes a User-role PromptMessage in
  chronological order. The persona's identity (System role) is
  filled in by the caller from IdentityState (not loaded into
  the turn frame today; future PR may add lazily).
- Per Joel's "Rust owns behavior" + "no TS shimming Rust outputs":
  the substrate owns the prompt-build path so TS PRG doesn't
  wrap a raw transcript into a model-specific prompt format.
- Wire shape: camelCase fields (systemPrompt, triggerMessageId)
  + lowercase role enum (system/user/assistant). Matches the
  de-facto chat-completion JSON.
- Returns None for empty frames (same contract as
  consolidated_inbox + rag_seed — empty inbox = no turn to plan).

This is the lazy output PR-4 inference-llm's
InferenceRequest.prompt_text expects. A follow-up PR will add the
turn-execute command that chains drain-turn-frame → response_prompt
→ inference/llm/request, making one Rust call execute the full
persona turn end-to-end.

Tests

5 new tests:
- response_prompt_returns_none_for_empty_frame
- response_prompt_carries_one_user_message_per_inbox_message
- response_prompt_system_prompt_is_none_pr1 (pins the IdentityState
  separation; flips when auto-load lands)
- response_prompt_trigger_matches_latest_message_id
- response_prompt_round_trips_through_serde (wire stability)

9/9 persona::turn_frame tests pass (5 new + 4 existing). No
regressions across other 2973 lib tests.

Stack

- Lane D PR-1/2/3 skeleton + drain_frame + rag_seed: already
  shipped
- Lane D drain-turn-frame command (#1398, mine just merged)
- THIS PR — ResponsePrompt lazy output (the inference-input
  lazy node the spec named)
- NEXT — turn-execute command that chains drain → response_prompt
  → inference/llm/request

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@joelteply joelteply merged commit 3a2fe24 into canary May 18, 2026
3 checks passed
@joelteply joelteply deleted the feat/lane-d-response-prompt-lazy-output branch May 18, 2026 18:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant