Repository navigation
Conversation
Adds resolve_group_badge (admin > user_group > tier precedence), operational_reason, and operational_result_from_code, which rebuilds a display-safe result from a stored reason code. None maps to the healthy no_supported_issue result, since history-copy rows carry a NULL code. Co-Authored-By: Claude Haiku 5.5 <[email protected]>
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
…etrics Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
…ransitions Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
run_startup_migrations now seeds user_activity from the legacy row one last time, then calls the new drop_legacy_snapshot_tables() on the analytics base store (both twins, DROP TABLE IF EXISTS). The seed returns 0 once the table is gone, so later boots are no-ops. The snapshot models, the store methods, the history copy and the legacy column migrations are deleted. app.py runs the migration in its own try, so a failure there still starts the worker. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…p's lock wait Co-Authored-By: Claude Opus 5.5 <[email protected]>
Removes user_state_counts from GET /overview and the status filter from GET /users (now 422), end to end: model, filters, SQL predicates, router, fixtures and tests. _legacy_state stays for the profile's state summary. Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
…s and allowlist reasons Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
…shot tables run_startup_migrations is now seed -> legacy rollup -> drop. Every user_lifecycle_daily_snapshots day with no fact row and no lifecycle-owned rollup is written as anonymous lifecycle_segment_count / lifecycle_transition rows in main's rollup_lifecycle_day shape, so the drop no longer destroys movement history older than the PR A 56-day copy. Either step raising skips the drop. Missing legacy tables are detected from the catalogue (sqlite_master, to_regclass) instead of English error text. rollup_lifecycle_day warns when a day has transitions but no facts; runs_by_* semantics documented. Co-Authored-By: Claude Opus 5.5 <[email protected]>
_GROUP_TOTALS_SQL counts partial rows per group; get_groups downgrades to partial when the (selected) window holds any, so the PR A history copy's zero-filled days are no longer labelled ready. Co-Authored-By: Claude Opus 5.5 <[email protected]>
aggregate_operator_cost_for_day (both twins) skips runs whose metadata.llm_execution.billing_mode is byok, so the profile's ATL platform model cost, /groups atl_cost_micro_usd and the permanent operator_cost_by_* rollups no longer include the user's own-key spend. Runs with no lane or malformed metadata keep counting. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…ifecycle history Retention cohorts always come from the facts-eligible population (facts hold no internal users, so admitting them counted eligible-never-retained), and /lifecycle history always falls back to the anonymous rollups. The lifecycle raw-read test now asserts every section is available, so a swallowed read fails it. Co-Authored-By: Claude Opus 5.5 <[email protected]>
When yesterday has no fact rows, the users page joins the latest landed snapshot_date (one MAX() read, both twins via a shared template), stamps the operational as_of from it, and prints WARNING: analytics.read.users_facts_stale, instead of silently reading every row as healthy/unpaid with an empty priority view. Co-Authored-By: Claude Opus 5.5 <[email protected]>
… failures Friction availability now equals funnel availability (top_failure_categories is computed from the funnel's reads); the count_states_for_date probe whose result was discarded is gone. Every silent except branch on the overview, lifecycle and groups read paths prints WARNING: analytics.read.<section>_failed category=<class>, never the message. Co-Authored-By: Claude Opus 5.5 <[email protected]>
backfill_analytics docstring and the script's --help now say inserted events update only the raw log and day rollups. CLAUDE.md marks the two snapshot recompute functions it names as deleted. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Contributor
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
…tion Review findings on #641 (store, job and migration side): - Derive lifecycle_transitions for the PR A history-copy days from consecutive fact days (first copied day from the legacy table) before the drop. - The daily job replaces a day's transition log instead of upserting movers only, re-derives the next day's log after a late recompute, and re-queues a recompute that fails part-way. - Fact reads apply admin/excluded filtering at read time; the replace spares rows the filter only hides. - rollup_day writes activation_users zero or not; the startup migration fills rolled-up days inside raw retention, independent of the drop. - The migration runs once, on the worker, retried before each tick; app.py no longer runs it on the event loop. - Delete the dead rollup_current_day. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Review findings on #641 (read side): - Overview attention, /lifecycle current and /operational state counts fall back to the latest landed fact day (labelled stale, or refused when the panel cannot say so) instead of empty counts; /groups reads coverage instead of assuming start < today landed. - The funnel is unavailable while a rolled-up day lacks activation_users. - Today's overview slice and the platform-cost read are internal-free, like the rollups they add to. - Retention counts ledger activity again; profile milestones are first occurrences (design SS6.12 amended); sessions crossing the 30-day cutoff are read whole. - The stale-facts WARNING logs once per stale day, not per request. - Drop the dead use_anonymous_rollups parameter and double chunking. Co-Authored-By: Claude Opus 5.5 <[email protected]>
top_failure_categories summed per-day distinct users unfiltered (user-days) and events under a billing/provider/model filter, under a field named affected_users. The anonymous rollups can give an exact event count and nothing else, so both paths now sum event_count rows plus today's events. The field is renamed event_count, the page column reads "Events", and rollup_day stops writing the affected_users family nothing reads. Design D13 amended. Closes #647 Co-Authored-By: Claude Opus 5.5 <[email protected]>
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
DO NOT MERGE until 2026-10-23 at the earliest (30 complete fact days) AND the prod read-only gate below has been re-run and passes. Merging deploys prod and drops two tables irreversibly.
Admin layer redesign PR B (design
docs/superpowers/specs/2026-09-15-admin-layer-redesign-design.md, plandocs/superpowers/plans/2026-09-15-admin-layer-redesign-prB-read-paths-delete.md). It moves every/api/admin/analytics/*read path off the legacy snapshot tables and ontouser_daily_facts/user_activity/ rollups. It deletesstates.py,lifecycle_backfill.py,maintenance.pyand the reaper sweep. It dropsuser_analytics_snapshotsanduser_lifecycle_daily_snapshotsat boot.Gate (run read-only on prod before lifting draft)
lifecycle_segment_count/lifecycle_transitionrollups before the drop. Re-count them, and confirm that every legacy segment is one of the six lifecycle segments.user_analytics_snapshots.activated_atexists, so the seed can read it.user_activitysanity: the users without a row are never-active users (123/271 on 2026-10-15).lifecycle_transitionsrow (the PR A history copy, 07-29..09-22, plus no-movement days). The first boot derives their log from consecutive fact days before the drop; the count is informational.Deploy
user_activity, legacy lifecycle rollup, history transition backfill, drop. Any of those failing skips the drop. Theactivation_usersrollup backfill runs regardless of that chain. A failure (e.g. the drop's 5 slock_timeout) is retried before each worker tick until it succeeds; the boot log prints the report.activation_usersbackfill fills every rolled-up day inside the 180-day raw-event retention from one grouped query. No operator step is needed:backfill_analyticswould not do it (it rebuilds rollups only for days where it inserts new events).snapshot_maintenance_failedevery 60 s until it exits. This is harmless.Value changes
/groupsand/lifecycleread the PR A history copy, which holds zero activity before about 2026-09-23. Retention marks those cells incomplete, and/groupsnow reportspartial. Recomputing those days from raw events is a follow-up (admin: recompute PR A's copied fact days from raw events before they expire #645).agent_runs.est_cost_usdand now excludes BYOK runs. Facts written since 2026-09-23 still carry BYOK estimates. Runs with noowner_user_idare excluded. "ATL Credits debited" now sums ledger consumption.include_internal=trueno longer widens retention,/groupsruns/cost, lifecycle segments, state counts, attention, the overview's funnel/failures/tokens/active/conversion/repeat, or/commercialplatform cost (today's raw slice is internal-free like the rollups)./groups, expiry rollups) on the next request./lifecyclecurrent counts and/operationalstate counts read the latest landed day (stale=true, statuspartial, coverage = that day) instead of zeros. Overview attention reads the day before yesterday at most, else it is unavailable./groupsispartialwhen any past day in the window has no fact rows.activation_usersrows./users:as_ofsays which day that is./overviewdropsuser_state_counts, and/users?status=returns 422. No frontend reads either.top_failure_categories[].affected_usersis renamedevent_countand counts failure events, filtered or not. On main it counted distinct users from a raw read. The page column now reads "Events".rollup_daystops writingaffected_usersrows. Closes admin: decide what the overview's failure count means #647.recent_runs= the sum ofruns_requestedover the 30 days through yesterday.MIN()(≤ 2 rows): a second raw-event read beside the timeline page, recorded as an amendment to design §6.12.evidence_event_idsis always[].Follow-ups
top_operational_reasonsneedsstatebefore PR D wires it.🤖 Generated with Claude Code