• feat: authored first-message presets — auto-seed on session-create (v0.19.8)

    vh released this 2026-07-06 14:23:53 -07:00 | 151 commits to main since this release

    Codifies 'give an agent a first message' (Worldtree #347): new module
    ratatoskr.first_message (FIRST_MESSAGE_PRESETS + seed_preset_first_message)
    seeds a preset agent's opening as a #347 authored turn-0 on every new session,
    wired into all three create paths — cli._amain (--send --new), tui._resolve_then_run
    (bare --new), web._create_session_endpoint (POST /api/sessions).

    seed_preset_first_message is strictly best-effort (INV-001): it soft-guards its
    inputs (return None, never assert), bounds the write with asyncio.wait_for so a
    stalled /history can't block create (the CLI/TUI clients disable read timeout for
    SSE), and swallows every exception except asyncio.CancelledError (which
    propagates) — so it can NEVER raise into or block the session-create path it is
    wired into. Per-content idempotency key → idempotent replay, no dup.

    Seeded with ratatoskr:sindra, whose opening greeting moved out of her card:
    her live system_prompt was PATCHed (non-destructive) to drop the Startup
    workaround the #347 first-message now replaces.

    Quality gate (both cross-frontier panels): heid-code-review returned zero
    implementation drift (2 test-only fixups applied); heid-bug-hunt caught the
    gap the conformance lens can't see — code matched the contract's narrow
    ERROR_ROUTING but INV-001's 'never raises' is broader — driving the broad-except

    • soft-guard + wait_for hardening above.

    Contract docs/contracts/first_message.contract.md (module-scoped, validated).
    TDD: 12 unit + 1 web wire-in; the 3 existing sindra bind tests gained a
    history-endpoint mock (creating a preset agent now auto-seeds). Suite 615 green,
    ruff+mypy clean. Auto-seed live-proven generation-free against personal :8081.

    Downloads