Skip to content

fix(stella-cli): record skill_usage on every execution path, not just the deck (#1872) - #1896

Merged
macanderson merged 4 commits into
mainfrom
fix/1872-skill-usage-all-paths
Aug 6, 2026
Merged

fix(stella-cli): record skill_usage on every execution path, not just the deck (#1872)#1896
macanderson merged 4 commits into
mainfrom
fix/1872-skill-usage-all-paths

Conversation

@macanderson

@macanderson macanderson commented Aug 6, 2026

Copy link
Copy Markdown
Owner

What & why

Store::record_skill_usage had exactly one call site — the deck's turn dispatch (crates/stella-cli/src/command_deck.rs) — whose own comment admitted "only for the deck path for now". So the default stella run pipeline path, the raw one-shot, both goal-turn drivers, and every other headless surface injected skills but wrote zero skill_usage rows. Every reader of the table under-counted for exactly the paths that produce most usage: the observatory's Sessions tab chips, the memory tab's skills aggregate, and skill appraisal (crates/stella-cli/src/memory/appraisals.rs) — and since appraisal feeds retirement, the gap could actively mis-steer which skills get retired.

Approach (as specced in the issue triage): the recorder moves to the shared execution seam. A new sibling module crates/stella-cli/src/agent/skill_usage.rs owns stamp_and_record_skill_usage, which subsumes the execution-id stamp every turn-building path already performed and records the selected skills at their pinned versions beside it. All five turn-building paths now hit the one function: the pipeline path and run_turn in agent.rs, both goal-turn drivers in agent/goal.rs, and the deck (whose private inline copy is deleted). Paths with no session memory (sub-sessions, resume, fleet) inject no skills and correctly record nothing.

Append-vs-once semantics (the table has no UNIQUE): the deck's existing semantics, now shared and documented in the module doc — one batch per execution, written at turn start (skills are injected regardless of how the turn ends). Each path begins its execution exactly once, so the append-only table holds at most one batch per execution by construction.

One deliberate behavior alignment: SessionMemory::selected_skills now honours the A/B recall control. Its doc already claimed it "reports exactly what was applied", but on a control turn the injection channels (recall_block_reported, pipeline_recall_block) suppress skills while selected_skills did not — so the deck recorded phantom usage for skills the model never saw, corrupting the exact appraisal signal this telemetry feeds. The guard aligns the report with the injection.

No schema change: skill_usage is already in prune.rs::DEPENDENT_TABLES.

Closes #1872

The witness

  • This PR includes a witness test (fails on main, passes here)

Two rungs:

  • agent::skill_usage::tests::a_pipeline_shaped_execution_records_skill_usage_at_the_seam — a non-deck ("pipeline"-kind) execution flowing through the seam leaves a skill_usage row keyed to that execution. On main the seam does not exist and a pipeline execution wrote zero rows (the sole recorder was the deck's inline block).
  • memory::tests::a_control_turn_reports_no_selected_skills — verified the artisanal way: with the ab_suppressed guard reverted, the test fails (test result: FAILED. 0 passed; 1 failed); with it, passes.

Deck behavior is preserved structurally: the deck now calls the same seam function whose semantics (turn-start, once per execution, best-effort) are the ones its inline copy implemented; the_seam_stamps_the_execution_id_onto_memory proves the seam also carries the reflection execution-id stamp it replaced.

The gate

  • cargo fmt --check (clean; fmt run on the touched crate)
  • clippy — scoped: cargo clippy -p stella-cli --all-targets -- -D warnings clean
  • tests — scoped: cargo test -p stella-cli --bin stella (1438 passed, 0 failed); rustdoc -D warnings clean for the crate. Full-workspace gate left to CI on this 16GB machine — flagging per build-economy policy.
  • Docs updated where behavior changed (module doc comment is the normative home for the seam semantics; stale "deck only" comment deleted with the code it described)
  • CLA signed
  • Closes #1872 appears both above and as a commit trailer

Nothing left behind

  • File-size guard: agent.rs 2266/2269, command_deck.rs 4672/4740 — both god files shrank or stayed under their ceilings; new logic is in the sibling module per the god-file rule.
  • Branch carries a merge of origin/main to pick up the fix(gate): unbreak all three of main's red gates in one PR, because one is not enough #1894 gate fixes (pre-existing baseline overages in stella-protocol/stella-tui were from the stale base, not this change).
  • Nothing else noticed and left unfixed.

Summary by Sourcery

Record skill-version usage telemetry at a shared execution seam so all turn-building paths write consistent skill_usage rows and maintain correct execution-id stamping for reflections.

New Features:

  • Add a shared stamp_and_record_skill_usage execution seam that stamps execution IDs onto session memory and records selected skills for all agent turn paths.

Bug Fixes:

  • Ensure SessionMemory::selected_skills respects A/B recall control so control turns report no skill usage and telemetry matches actual injections.
  • Fix omission where non-deck execution paths (pipeline, one-shot, goal turns) were not recording any skill_usage telemetry despite injecting skills.

Enhancements:

  • Refactor per-path execution ID stamping and deck-only skill usage recording into a centralized agent skill usage module for reuse across surfaces.

Tests:

  • Add witness tests confirming the shared seam records skill usage for pipeline-shaped executions and still stamps execution IDs onto memory without recording phantom usage.
  • Add a memory test asserting that control turns report no selected skills, aligning reports with injection behavior.

Stella Test added 4 commits August 6, 2026 04:38
… the deck

Store::record_skill_usage had exactly one caller — the deck's turn
dispatch — so the default `stella run` pipeline path, the raw one-shot,
goal runs, and every other headless surface injected skills but wrote no
skill_usage rows. The Sessions tab, the memory tab's skills aggregate,
and skill appraisal (which feeds retirement) all under-counted for the
paths that produce most usage.

The recorder now lives at the shared execution seam
(agent::skill_usage::stamp_execution_and_record_skill_usage), beside the
execution-id stamp every turn-building path already performs: the
pipeline path, run_turn, both goal-turn drivers, and the deck all hit
one function. Semantics are the deck's, now shared: one batch per
execution, written at turn start, best-effort.

selected_skills now honours the A/B recall control, so a control turn
that injects no skills records no phantom usage — aligning the report
with the injection channels it describes.

Closes #1872

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @macanderson, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@vercel

vercel Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
stella-cli-docs Ignored Ignored Aug 6, 2026 6:33pm

@sourcery-ai

sourcery-ai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Reviewer's Guide

Centralizes skill-usage telemetry and execution-id stamping into a shared agent seam so all turn-building paths consistently record skill_usage rows and honor A/B recall control, while preserving deck semantics and adding targeted tests.

Flow diagram for shared skill_usage execution seam and callers

flowchart TD
    subgraph Turn_builders
        run_pipeline_one_shot[run_pipeline_one_shot]
        run_turn[run_turn]
        run_goal_turn[run_goal_turn]
        run_goal_pipeline_turn[run_goal_pipeline_turn]
        run_deck_session[run_deck_session]
    end

    seam[stamp_and_record_skill_usage]
    memory_set[SessionMemory.set_execution_id]
    selected[SessionMemory.selected_skills]
    pinned[skill_manager.pinned_versions]
    record[Store.record_skill_usage]

    run_pipeline_one_shot --> seam
    run_turn --> seam
    run_goal_turn --> seam
    run_goal_pipeline_turn --> seam
    run_deck_session --> seam

    seam --> memory_set
    memory_set --> selected
    selected -->|non_empty, ab_not_suppressed| pinned
    selected -->|empty_or_ab_suppressed| end_noop[(no skill_usage rows)]

    pinned --> record
    record --> end_rows[(skill_usage rows keyed by execution_id)]
Loading

File-Level Changes

Change Details Files
Introduce shared execution seam helper that stamps execution id on SessionMemory and records skill usage, and wire all turn-building paths through it.
  • Add new agent::skill_usage module with stamp_and_record_skill_usage that sets execution_id, computes selected skills, resolves pinned versions, and writes SkillUsageRow entries best-effort.
  • Re-export stamp_and_record_skill_usage from agent so it can be used by multiple callers.
  • Replace per-path execution-id stamping in run_turn, run_pipeline_one_shot, run_goal_turn, run_goal_pipeline_turn, and deck run_deck_session with calls to the shared seam helper.
  • Ensure paths lacking execution or session memory become no-ops, matching their lack of skill injection.
crates/stella-cli/src/agent/skill_usage.rs
crates/stella-cli/src/agent.rs
crates/stella-cli/src/agent/goal.rs
crates/stella-cli/src/agent.rs
crates/stella-cli/src/command_deck.rs
Align SessionMemory::selected_skills reporting with A/B recall control semantics and expose minimal testing hook for execution id.
  • Gate selected_skills on ab_suppressed so control turns report no skills, matching injection behavior and avoiding phantom usage in telemetry.
  • Add execution_id_for_test accessor under cfg(test) to allow seam tests to verify stamping behavior.
crates/stella-cli/src/memory.rs
Add tests covering the new seam behavior and A/B control semantics for skill selection.
  • Add seam-focused tests verifying that a pipeline-shaped execution records skill usage, that the seam stamps execution id without recording phantom usage when no skills are selected, and that absent memory or execution is a safe no-op.
  • Add memory test ensuring a control turn reports no selected skills while an armed turn with the same prompt does select skills.
crates/stella-cli/src/agent/skill_usage.rs
crates/stella-cli/src/memory/tests.rs

Assessment against linked issues

Issue Objective Addressed Explanation
#1872 Record skill_usage telemetry for all execution paths (pipeline, headless, run, goal, etc.) wherever skills are selected/injected, not just the deck path, by wiring selection through the shared execution/persistence seam.
#1872 Preserve and clearly define deck semantics for skill_usage (one batch per execution, written at turn start; handle append-vs-once semantics and document them), and reuse these semantics across all paths.

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@macanderson
macanderson merged commit 9b2aa27 into main Aug 6, 2026
12 checks passed
@macanderson
macanderson deleted the fix/1872-skill-usage-all-paths branch August 6, 2026 19:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

stella-cli: skill_usage is recorded only on the deck path — pipeline and headless runs report zero skill telemetry

1 participant