Story-3050 Walkthrough

Outcome: Vani now reads counsel-authored personalisation from the broker's top-level memory_pack.v1 and places it in the CORE instruction prefix before matter-specific material. Counsel's text reaches the model byte-for-byte; an absent or empty personalisation adds no marker, header, or prompt byte.

Boundary. This is the agents reader half only. pramaan-functions PR #860 owns the store, validation, and top-level invoke-envelope assembly. Vani remains read-only. There is no detector, confirmation flow, feature flag, normaliser, summariser, or rename of the shared MiraConverseInput wire type.

The two closed gaps

BeforeAfter
The broker sent memory_pack beside input, but Vani only validated the nested input, so MiraConverseInput.memory_pack was None. runtime.handle_request copies the authoritative top-level pack into the converse input at the single ingress seam. Command and map-command contracts are unchanged.
The local pack's text field was treated as a matter/session fold and rendered after the frame as SESSION_MEMORY. text is counsel's cross-matter CORE personalisation. session_fold remains the matter-specific fold after the frame. The two meanings are explicit and independently tested.

Actual model-request order

ModelRequest
  instructions:
    Vani static instructions
    CORE PERSONALISATION — counsel-authored standing instructions.
    [CORE_PERSONALISATION_BEGIN]
    {counsel text exactly as stored}
    [CORE_PERSONALISATION_END]

  user material:
    matter metadata
    <<MATTER_FRAME_…>>
    <<SESSION_MEMORY_…>>       (only the matter/session fold)
    <<CONTEXT_BUNDLE_…>>
    history, tool results, counsel message

The implementation uses Pydantic AI's native per-run Agent.iter(..., instructions=...) seam. CORE therefore precedes the user prompt structurally; no custom message machinery is introduced. The prompt version moves from mira.converse.v6 to mira.converse.v7.

Acceptance evidence

RequirementExecutable proof
Top-level store output reaches Vani test_top_level_memory_pack_reaches_the_converse_input_verbatim feeds a producer-shaped top-level pack through handle_request and inspects the typed converse input.
CORE is first test_personalisation_is_core_first_and_verbatim_in_the_model_request captures the real Pydantic AI ModelRequest, proves CORE is in instructions, and proves frame/fold ordering in user material.
Verbatim counsel text The same model-request test uses leading/trailing spaces, a newline, an em dash, and Devanagari text, then extracts the delimited payload and asserts exact equality.
No personalisation changes zero bytes test_empty_personalisation_is_byte_identical_to_no_memory_pack fixes the nonce, compares the assembled prompts byte-for-byte, and proves both runs add no per-run instructions.

Verification

uv run ruff check .  → All checks passed
uv run pytest -q     → 444 passed

Focused Vani suite   → 264 passed
Decision-number gate → 6 passed