Skip to content

feat(review_hog): stamp ai_session_id on every review turn generation - #75592

Closed
sortafreel wants to merge 3 commits into
masterfrom
posthog-code/reviewhog-ai-session-id
Closed

feat(review_hog): stamp ai_session_id on every review turn generation#75592
sortafreel wants to merge 3 commits into
masterfrom
posthog-code/reviewhog-ai-session-id

Conversation

@sortafreel

@sortafreel sortafreel commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Problem

ReviewHog's LLM generations can't be attributed to the PR review they served. $ai_generation events carry task-level keys only (task_id, ai_stage), so per-review cost or latency questions need multi-hop joins, and ad-hoc generation queries can't filter by review at all — a review turn's ~hundreds of generations have no common key.

Changes

  • Task.create_and_run accepts an ai_session_id and stashes it in run state, mirroring ai_stage exactly; threaded through create_task_and_trigger / MultiTurnSession.
  • ReviewHog stamps {report_id}:r{run_index} on every LLM call a review turn makes — sandbox stages through the task chain, one-shot chunking/selection/dedup through the direct gateway header.
  • The key travels unreserved (ai_session_id) because $-keys are stripped at the ai-gateway header boundary; the llm-gateway callback promotes it to the native $ai_session_id (materialized column + bloom-filter index, AI-observability session grouping) where the event's properties are final — on success and failure captures.
  • Companion agent-server change forwards the new state key: feat(agent): forward ai_session_id run-state key to gateway properties code#4011. Merge order is free in both directions: an absent state key emits no header, and an unknown state key is ignored.
  • ARCHITECTURE.md updated in the same PR.

How did you test this code?

  • Extended the tasks model tests: the state-stash pair now covers ai_session_id alongside ai_stage (threaded and omitted cases) — the regression being a silently dropped key that breaks the whole stamping chain downstream.
  • New llm-gateway callback test locks the ai_session_id$ai_session_id promotion — losing it would keep transport working while silently breaking native session grouping, which no other test observes.
  • Agent limitations: authored in a sandboxed environment without the dev stack — ruff check / ruff format pass and all files compile; pytest and repo-wide mypy run in CI.

Automatic notifications

  • Publish to changelog?
  • Alert Sales and Marketing teams?

Docs update

ARCHITECTURE.md (the product's own doc) is updated in this PR.

🤖 Agent context

Autonomy: Human-driven (agent-assisted)

  • Authored by Claude via a PostHog Code cloud task; follow-up to feat(review_hog): link review turns to their LLM cost on the event #75565 (which joins cost per turn via task ids on the completion event) — this makes generations directly filterable by review, requested while building cost-by-PR-size views.
  • Skills invoked: /writing-tests and /writing-code-comments (repo skills, applied as gates).
  • Decisions: transport unreserved + promote in the gateway, rather than sending $ai_session_id from clients — the shared header builders document that $-keys are silently dropped at the ai-gateway boundary, so a reserved key would work on one routing path and vanish on the other; promotion happens where properties are final and covers both gateway routings' futures. Session id format {report_id}:r{run_index} gives per-turn equality and per-report prefix matching.

Why: requested so a review turn's generations carry one queryable key — completing the cost-attribution story started in #75565.


Created with PostHog Code

Recover the turn's sandbox runs by the Temporal workflow-id branding every run already carries (_sandbox_workflow_id_prefix), through a new read-only tasks facade helper, and stamp sandbox_task_ids + summed token totals + run count onto reviewhog_review_completed. sandbox_task_ids joins to $ai_generation.task_id for exact per-turn dollar cost — the gateway's cost numbers stay the single source of truth instead of duplicating pricing server-side. Prefix matching is separator-suffixed so PR 12 never matches PR 123, bounded to the turn's window (Temporal allows one running turn per PR), and best-effort: a lookup failure nulls the linkage properties, never the capture.

Generated-By: PostHog Code
Task-Id: 77db6432-21d6-400a-ad79-7ce81def58cf
Thread an ai_session_id through the tasks facade into run state (mirroring ai_stage exactly), and set it from ReviewHog to {report_id}:r{run_index} on every LLM call a turn makes — sandbox stages via Task.create_and_run, one-shots via a direct gateway header. $ai_session_id is first-class LLM-analytics taxonomy (materialized column + bloom-filter index), so a turn's generations become directly filterable by review turn and group as one session in AI observability. The sandbox path lights up once the agent-server forwards the new state key (companion PostHog/code change); the one-shot path works immediately.

Generated-By: PostHog Code
Task-Id: 77db6432-21d6-400a-ad79-7ce81def58cf
Reserved $-keys are stripped at the ai-gateway header boundary, so callers transport the session key unreserved (ai_session_id, mirroring ai_stage) and the llm-gateway callback promotes it to the native $ai_session_id — materialized column, bloom-filter index, AIO session grouping — where the event's properties are final, on both success and failure captures. Covered by a new callback test.

Generated-By: PostHog Code
Task-Id: 77db6432-21d6-400a-ad79-7ce81def58cf
@trunk-io

trunk-io Bot commented Jul 30, 2026

Copy link
Copy Markdown

Merging to master in this repository is managed by Trunk.

  • To merge this pull request, check the box to the left or comment /trunk merge below.

After your PR is submitted to the merge queue, this comment will be automatically updated with its status. If the PR fails, failure details will also be posted here

@github-actions

Copy link
Copy Markdown
Contributor

Hey @sortafreel! 👋

It looks like your git author email on this PR isn't your @posthog.com address (woutut@gmail.com). Since you're on the PostHog team, it's worth pointing your local git author email at your @posthog.com address. Why it matters:

  • Consistent work identity in git history — internal tooling that attributes commits to team members keys off your @posthog.com address.
  • Keeps team contributions easy to tell apart from external community ones when scanning history.

You can fix it for this repo with:

git config user.email "you@posthog.com"

Or set it globally with git config --global user.email "you@posthog.com". No need to redo this PR — just a nudge for next time. 🙂

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.

1 participant