Skip to content

stella-store: project behavioural tendencies per turn (turn_tendencies) so they aggregate beyond one execution #1868

Description

@macanderson

Problem

Behavioural events — retry, retries_exhausted, loop_detected (kind + aborted), budget_denied, compaction (before/after tokens), policy_decision (kind), speculation_discarded, steered, provider_fallback, usage_incomplete — live only in the events journal. The observatory's /api/execution-tendencies (added with the Sessions tab, see crates/stella-observatory/src/sessions.rs::execution_tendencies) folds them per execution, which is the sanctioned per-execution events read. But session-, workspace-, and org-level tendency trends are impossible without a projection: the observatory's journal rule ('a cross-execution view needs a projection, not a wider WHERE', crates/stella-observatory/src/db.rs::execution_journal docs) forbids the query that would compute them.

Build

A turn_tendencies table in crates/stella-store/src/ddl.rs (one row per execution: retries, retries_exhausted, loop_detections, loop_aborts, stagnations, budget_denials, compactions, tokens_reclaimed, policy_blocked, secrets_detected, speculation_discarded, steered, provider_fallbacks, usage_incomplete), written at turn end from record_execution_end (crates/stella-cli/src/agent/persistence.rs, beside finalize_execution_reflection) — or live-projected like tool_calls v18. crates/stella-serve/src/observe/tally.rs::TallyFold already computes exactly this vector in memory; reuse its fold rather than writing a second one. Add the table to prune.rs::DEPENDENT_TABLES (its test enforces coverage).

Then the observatory can aggregate per session (JOIN executions ON session_id) and per day, and /api/execution-tendencies can read the projection with the journal fold as fallback for old stores.

Verify

Witness: seed an execution whose journal carries a retry + a loop_detected via Store::record_event, finish the turn, assert the turn_tendencies row exists with those counts — fails on main (no table). Observatory side: extend crates/stella-observatory/tests/schema_conformance.rs.

Constraints

  • No I/O in stella-core (invariant 2); the fold is pure, the write goes through stella-store.
  • Migration bumps migrations::SCHEMA_VERSION; the observatory must keep degrading on stores without the table (is_missing_schema).

Refs #1461, #1476.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Polish — worth doing, not urgentarea:storestella-store — DuckDB persistence & telemetryfeatureNew capability or improvement

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions