Skip to content

feat(replay-vision): restore gemini-3-flash-preview as 5-credit default#73026

Merged
arnohillen merged 2 commits into
masterfrom
ahillen/replay-vision-restore-gemini-3-flash
Jul 23, 2026
Merged

feat(replay-vision): restore gemini-3-flash-preview as 5-credit default#73026
arnohillen merged 2 commits into
masterfrom
ahillen/replay-vision-restore-gemini-3-flash

Conversation

@arnohillen

Copy link
Copy Markdown
Contributor

Problem

Yesterday's #72713 retired Gemini 3 Flash (gemini-3-flash-preview) and switched the default scanner model to gemini-3.6-flash, which bills at 15 credits per observation instead of 5. We want the cheaper 5-credit model back as the default so new scanners start at the familiar lower price point.

Changes

Restores gemini-3-flash-preview as a selectable model and the default for new scanners, at 5 credits per observation. The lineup is now three models across two Google tiers:

model tier credits/observation
gemini-3.5-flash-lite flash lite 2 (budget)
gemini-3-flash-preview flash 5 (default)
gemini-3.6-flash flash 15
  • Adds GEMINI_3_FLASH_PREVIEW back to the ScannerModel enum with display name "Gemini 3 Flash (preview)" so it reads distinctly from the stable "Gemini 3.6 Flash".
  • Un-retires it in billing.GEMINI_MODELS at 5 credits. That is exactly what the margin formula produces from its token prices (0.50 in / 3.00 out per 1M tokens at the 3.75x target), so pricing stays consistent with the rest of the lineup.
  • Flips the estimate serializer default and the frontend DEFAULT_MODEL to the preview, and regenerates OpenAPI/MCP types.
  • Migration 0053 updates the field choices (state-only AlterField, no DB schema change).

Note

Existing scanners are unaffected. Migration 0052 already remapped anything on gemini-3-flash-preview to gemini-3.6-flash, so this only changes what new scanners default to. gemini-3-flash-preview is a preview id, so if Google retires it we remap like 0052 did.

How did you test this code?

Automated tests I (Claude) ran locally, all passing:

  • test_billing.py, including the mirror test (enum ↔ GEMINI_MODELS) and the flash margin test, which I parameterized to also assert gemini-3-flash-preview's 5 credits equals the formula output. That guards against a future token-price change silently leaving the credit price stale, which no existing test caught (the mirror test only checks membership).
  • test_api.py estimate tests. I updated test_estimate_counts_only_in_window_sessions to expect 5 credits / 15 per month now that the default model changed.

I regenerated types with hogli build:openapi and ran hogli ci:preflight (0 failures). I did not get the full frontend typecheck to green in my worktree because the quill workspace packages are not built there (an environment quirk unrelated to this change). replay_vision itself reports zero type errors.

Automatic notifications

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

🤖 Agent context

Autonomy: Human-driven (agent-assisted)

Arnaud asked me to double-check whether the flash model costs 5 or 15 credits after yesterday's PRs, then to bring back the 5-credit model as the default with a version-explicit name. I (Claude) traced the pricing history and confirmed the 5-credit model was gemini-3-flash-preview (not the "3.1" flash-lite preview, which was 2 credits and never the default), verified 5 credits sits exactly on the margin formula, and made the change.

Skills invoked: /improving-drf-endpoints (serializer default), /django-migrations (choices migration), /writing-tests (test changes).

Decisions: kept the change additive (added the preview alongside the existing 2- and 15-credit models rather than reverting the whole #72713 lineup) since existing scanners already migrated to gemini-3.6-flash. Considered adding a pro tier but left it out per Arnaud's call to keep the three-model lineup. Named it "Gemini 3 Flash (preview)" to make the version explicit next to "Gemini 3.6 Flash".

Brings back Gemini 3 Flash (gemini-3-flash-preview) as a selectable model
and the default for new scanners, at 5 credits per observation. PR #72713
had retired it in favor of the 15-credit gemini-3.6-flash default.

The selectable lineup is now three models across two Google tiers:

- gemini-3.5-flash-lite: 2 credits (budget)
- gemini-3-flash-preview: 5 credits (default, flash preview)
- gemini-3.6-flash: 15 credits (stable flash)

5 credits is exactly the margin-formula output for its token prices
(0.50 in / 3.00 out per 1M tokens at the 3.75x target margin), so pricing
stays internally consistent with the rest of the lineup.

Existing scanners are unaffected. Migration 0052 already remapped anything
on gemini-3-flash-preview to gemini-3.6-flash, so this only adds the model
back for new scanners. gemini-3-flash-preview is a preview id, so watch for
Google retiring it and remap like 0052 if that happens.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@arnohillen arnohillen self-assigned this Jul 22, 2026
@trunk-io

trunk-io Bot commented Jul 22, 2026

Copy link
Copy Markdown

😎 This pull request was merged.

@arnohillen arnohillen added the stamphog Request AI approval (no full review) label Jul 22, 2026
@arnohillen
arnohillen requested review from a team, TueHaulund, fasyy612 and ksvat and removed request for a team July 22, 2026 22:03
@github-actions

github-actions Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

🤖 CI report

Bundle size — no change

Uncompressed size of every built .js bundle, compared against the base branch.

Total: 64.67 MiB · no change

No file changed by more than 1000 B.

Posted automatically by build-bundle-size-report · uncompressed bytes from dist-report

Eager graph — within budget

How much code each root ships on the eager path — downloaded and parsed before the surface is interactive. Measured from the esbuild output chunks (post-tree-shake, static imports only); lazy import() / React.lazy chunks are not counted.

Root Eager (shipped) Δ vs base Budget
entry (logged-out pages, app bootstrap)
src/index.tsx
1.24 MiB · 22 files no change ███░░░░░░░ 27.5% of 4.51 MiB
authenticated shell (every logged-in page)
src/scenes/AuthenticatedShell.tsx
8.21 MiB · 3,002 files no change ████████░░ 84.6% of 9.71 MiB

🟢 node_modules/monaco-editor/ stays out of src/index.tsx
🟢 src/lib/components/ActivityLog/describers stays out of src/index.tsx
🟢 [object Object] stays out of src/index.tsx
🟢 [object Object] stays out of src/index.tsx
🟢 node_modules/monaco-editor/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/lib/components/ActivityLog/describers stays out of src/scenes/AuthenticatedShell.tsx
🟢 [object Object] stays out of src/scenes/AuthenticatedShell.tsx
🟢 [object Object] stays out of src/scenes/AuthenticatedShell.tsx

Largest files eagerly shipped from src/index.tsx
Size File
126.8 KiB ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
24.6 KiB ../node_modules/.pnpm/buffer@6.0.3/node_modules/buffer/index.js
6.3 KiB ../node_modules/.pnpm/react@18.3.1/node_modules/react/cjs/react.production.min.js
4.5 KiB ../node_modules/.pnpm/@jspm+core@2.1.0/node_modules/@jspm/core/nodelibs/browser/process.js
3.9 KiB ../node_modules/.pnpm/scheduler@0.23.2/node_modules/scheduler/cjs/scheduler.production.min.js
1.4 KiB ../node_modules/.pnpm/base64-js@1.5.1/node_modules/base64-js/index.js
1.3 KiB src/RootErrorBoundary.tsx
912 B ../node_modules/.pnpm/ieee754@1.2.1/node_modules/ieee754/index.js
789 B src/scenes/ChunkLoadErrorBoundary.tsx
762 B src/index.tsx
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx
Size File
281.5 KiB ../node_modules/.pnpm/posthog-js@1.407.1/node_modules/posthog-js/dist/rrweb.js
267.7 KiB ../node_modules/.pnpm/@posthog+icons@0.38.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js
236.0 KiB src/taxonomy/core-filter-definitions-by-group.json
226.1 KiB ../node_modules/.pnpm/posthog-js@1.407.1/node_modules/posthog-js/dist/module.js
167.1 KiB src/queries/validators.js
154.3 KiB ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js
126.8 KiB ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
105.8 KiB src/lib/api.ts
94.0 KiB ../packages/quill/packages/quill/dist/index.js
93.3 KiB ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js

Posted automatically by check-eager-graph · sizes are eager output bytes (shipped, post-tree-shake) from the esbuild metafile · part of #32479

Toolbar bundle — eager 2.18 MiB within budget

What the toolbar ships to customer pages, measured from the esbuild output (minified, post-tree-shake). The eager set is the entry plus everything statically imported from it — fetched before any feature runs; deferred chunks load lazily. The eager guardrail is 5.72 MiB. Each output file must also stay below 10 MB, where CloudFront stops compressing it. The module boundary is enforced separately by check-toolbar-graph.

Metric Size Δ vs base Budget
Eager (shipped)
entry + static imports
2.18 MiB · 17 files no change ████░░░░░░ 38.1% of 5.72 MiB
Deferred (lazy) 2.07 MiB · 33 files no change n/a — loads on demand
Loader dist/toolbar.js 1.1 KiB no change █░░░░░░░░░ 5.8% of 19.5 KiB
Largest eagerly-shipped chunks
Size File
713.8 KiB dist/toolbar/toolbar-app-HY7HJI4V.css
545.0 KiB dist/toolbar/chunk-chunk-RQ4FN27S.js
484.2 KiB dist/toolbar/chunk-chunk-QS5AHYGW.js
133.6 KiB dist/toolbar/chunk-chunk-SYFILNLU.js
131.8 KiB dist/toolbar/chunk-chunk-T5KY5WYR.js
71.0 KiB dist/toolbar/toolbar-app-IWQPCR2K.js
69.0 KiB dist/toolbar/chunk-chunk-27JL52RE.js
35.6 KiB dist/toolbar/chunk-chunk-ZOYUTNIC.js
20.9 KiB dist/toolbar/chunk-chunk-IIQH4XLX.js
12.2 KiB dist/toolbar/chunk-chunk-PIK3PADE.js

Posted automatically by check-toolbar-size · sizes are toolbar output bytes (shipped, post-tree-shake) from the esbuild metafile

Dist folder size — 🔺 +1.2 KiB (+0.0%)

Total size of the built frontend/dist folder (all assets), compared against the base branch.

Total: 1357.65 MiB · 🔺 +1.2 KiB (+0.0%)

⚠️ Django migration SQL — 1 new migration to review

We've detected new migrations on this PR. Review the SQL output for each migration:

products/replay_vision/backend/migrations/0053_alter_replayscanner_model.py

BEGIN;
--
-- Alter field model on replayscanner
--
-- (no-op)
COMMIT;

Last updated: 2026-07-23 09:59 UTC (234d1bd)

Django migration risk — migration analysis complete

We've analyzed your migrations for potential risks.

Summary: 0 Safe | 1 Needs Review | 0 Blocked

⚠️ Needs Review

May have performance impact

replay_vision.0053_alter_replayscanner_model
  └─ #1 ⚠️ AlterField
     Field alteration may cause table locks or data loss (check if changing type or constraints)
     model: replayscanner, field: model, field_type: CharField

Last updated: 2026-07-23 09:59 UTC (234d1bd)

@arnohillen
arnohillen requested a review from a team July 23, 2026 09:00
@arnohillen
arnohillen marked this pull request as ready for review July 23, 2026 09:50
@arnohillen
arnohillen enabled auto-merge (squash) July 23, 2026 09:50
@github-actions

github-actions Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

🦔 Hogbox preview · ✅ ready

▶ Open the preview

🔑 Login test@posthog.com / 12345678 (demo data)
🧩 Running this PR's backend and frontend, on the PostHog :master base
🔗 Link stable across rebuilds — a re-push swaps the box underneath, the URL stays
🔒 Access tailnet only (PostHog VPN)
🛠️ Admin inspect & debug state in hogland
💤 Idle sleeps after ~30 min idle (snapshot to S3, zero node cost) and wakes on your next visit in ~30s, behind a brief "waking up" screen

commit 234d1bd · box box-6d8cd83273fd · ready in 939s (push → usable) · build log · rebuilds on every push, torn down on close

@stamphog

stamphog Bot commented Jul 23, 2026

Copy link
Copy Markdown

Note

🤖 stamphog reviewed 234d1bdd36f00182bbb3714ac2126a61a9b86d9d — verdict: REFUSED

Gates denied this PR for touching billing logic and a migration, which is risky territory; the only review present is COMMENTED (not approved), with an unresolved style nit — not independent assurance on the pricing/migration change itself.

  • greptile-apps[bot] reviewed the current head.
  • Deny-list gate failed: change touches billing.GEMINI_MODELS pricing and a Django migration (0053_alter_replayscanner_model)
  • Tier gate failed: classified T2-never (134 lines, 12 files, two areas)
  • Only review is COMMENTED, not APPROVED, and there's an unresolved inline thread from Greptile — no independent sign-off covering the billing/migration change
Gate mechanics and policy version
Gate Result
prerequisites all clear
deny-list matches: billing, migrations
size 57L, 6F substantive, 134L/12F incl. docs/generated/snapshots — within ceiling
tier classified as T2-never: T2-never (134L, 12F, two-areas, feat)
stamphog 2.0.0b3 .stamphog/policy.yml @ 300102e · reviewed head 234d1bd

Updated in place — this replaces 1 earlier stamphog review(s) on this PR.

@stamphog stamphog Bot removed the stamphog Request AI approval (no full review) label Jul 23, 2026
@greptile-apps

greptile-apps Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
products/replay_vision/backend/tests/test_billing.py:89
**Use standard test parameterization**

This synchronous test uses `pytest.mark.parametrize` even though it needs no pytest-only fixture or async support. Using the repository-standard `parameterized.expand` avoids introducing a second parameterization convention and an otherwise unnecessary pytest import.

Reviews (1): Last reviewed commit: "Merge branch 'master' into ahillen/repla..." | Re-trigger Greptile

Comment thread products/replay_vision/backend/tests/test_billing.py

@fasyy612 fasyy612 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.

sweeet 👌

@arnohillen
arnohillen merged commit 2f7095e into master Jul 23, 2026
295 of 304 checks passed
@arnohillen
arnohillen deleted the ahillen/replay-vision-restore-gemini-3-flash branch July 23, 2026 10:30
@deployment-status-posthog

deployment-status-posthog Bot commented Jul 23, 2026

Copy link
Copy Markdown

Deploy status

Environment Status Deployed At Workflow
dev ✅ Deployed 2026-07-23 10:57 UTC Run
prod-us ✅ Deployed 2026-07-23 11:17 UTC Run
prod-eu ✅ Deployed 2026-07-23 11:18 UTC Run

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.

2 participants