ref(seer): Genericize night shift result table#114790
Merged
Conversation
Renames SeerNightShiftRunIssue → SeerNightShiftRunResult (state-only; db_table preserved) and adds a `kind` discriminator + per-row `extras` JSON to support nightly per-org work beyond agentic triage. Triage's existing `action` column is moved into extras["action"] via a deploy-time backfill. Legacy columns (action, triage_strategy, error_message) are marked SafeRemoveField MOVE_TO_PENDING; their physical drop ships in a follow-up.
Contributor
|
This PR has a migration; here is the generated SQL for for --
-- Custom state/database change combination
--
-- (no-op)
--
-- Alter field run on seernightshiftrunresult
--
-- (no-op)
--
-- Add field kind to seernightshiftrunresult
--
ALTER TABLE "seer_nightshiftrunissue" ADD COLUMN "kind" varchar(256) DEFAULT 'agentic_triage' NOT NULL;
--
-- Add field extras to seernightshiftrunresult
--
ALTER TABLE "seer_nightshiftrunissue" ADD COLUMN "extras" jsonb DEFAULT '{}'::jsonb NOT NULL;
--
-- Alter field group on seernightshiftrunresult
--
ALTER TABLE "seer_nightshiftrunissue" ALTER COLUMN "group_id" DROP NOT NULL;
--
-- Alter field action on seernightshiftrunresult
--
ALTER TABLE "seer_nightshiftrunissue" ALTER COLUMN "action" DROP NOT NULL;
--
-- Alter field triage_strategy on seernightshiftrun
--
ALTER TABLE "seer_nightshiftrun" ALTER COLUMN "triage_strategy" DROP NOT NULL;
--
-- Create index seer_nights_run_id_d5406e_idx on field(s) run, kind of model seernightshiftrunresult
--
CREATE INDEX CONCURRENTLY "seer_nights_run_id_d5406e_idx" ON "seer_nightshiftrunissue" ("run_id", "kind");
--
-- Raw Python operation
--
-- THIS OPERATION CANNOT BE WRITTEN AS SQL
--
-- Moved seernightshiftrunresult.action field to pending deletion state
--
-- (no-op)
--
-- Moved seernightshiftrun.triage_strategy field to pending deletion state
--
-- (no-op)
--
-- Raw Python operation
--
-- THIS OPERATION CANNOT BE WRITTEN AS SQL
--
-- Moved seernightshiftrun.error_message field to pending deletion state
--
-- (no-op) |
Without this, runs that had an error_message recorded against the legacy column would return errorMessage: null from the API after the column is removed from model state via SafeRemoveField(MOVE_TO_PENDING). Adds a second RunPython op (run before the error_message SafeRemoveField) and extends the migration test to cover both the existing action backfill and the new error_message backfill.
Mypy flagged the missing annotation on the migration test's setup_before_migration override.
Dropping the db_default in the same migration that adds the NOT NULL column breaks rolling deploys: old replicas still INSERTing without kind would fail with a NOT NULL violation between when the migration applies and when those replicas are replaced. Defer the db_default drop to the follow-up PR2 (the same one that runs SafeRemoveField DELETE for the legacy columns), which already requires PR1 to be fully deployed.
Contributor
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit adea73a. Configure here.
Pre-migration the triage_strategy column was a required CharField, always set to "agentic_triage" — including for runs that produced no result rows (failed quota check, no eligible projects, dry runs). My earlier serializer change derived the legacy alias from result-row presence, silently flipping triageStrategy to null for those runs. Hardcode it back to "agentic_triage" so the API surface matches the old behavior. Multi-kind serializer logic ships with the feature PR.
The migration has 12 operations including a CONCURRENTLY index, so TestMigrations.setUp's roll-back/forward cycle was hovering at or over CI's 120s fail-slow budget per test. The migration itself is already exercised by: - Direct application against dev DB with real data (47 result rows backfilled correctly). - The full night-shift test suite (49 tests) running against the post-migration schema with --create-db. - The two RunPython callbacks are simple idempotent loops; the cost of an integration test has stopped paying for itself.
This reverts commit f7cd5c3.
Drive-by edit from the original PR1 commit. No reason for it.
trevor-e
commented
May 5, 2026
| group=c.group, | ||
| action=c.action, | ||
| seer_run_id=str(seer_run_id), | ||
| extras={"action": str(c.action)}, |
Member
Author
There was a problem hiding this comment.
Will have to update our dashboard.
cleptric
pushed a commit
that referenced
this pull request
May 5, 2026
Repurposes the existing night-shift result table so it can host more than just agentic triage. No behavior change. - Renames `SeerNightShiftRunIssue` → `SeerNightShiftRunResult` (state-only via `SeparateDatabaseAndState` + `RenameModel`; underlying Postgres table keeps the historical `seer_nightshiftrunissue` name). - Adds a `kind` discriminator (with a `NightShiftRunResultKind` enum) and a per-row `extras` JSON. - Migrates `action`, `error_message`, and `triage_strategy` data into JSON (`extras`) and marks the legacy columns `SafeRemoveField(MOVE_TO_PENDING)`. Physical drop ships in a follow-up. - Serializer keeps `issues`, `triageStrategy`, and `errorMessage` aliases for the existing frontend; new `results` key is the canonical shape going forward.
trevor-e
added a commit
that referenced
this pull request
May 5, 2026
**Stacked on #114790** — review and land that one first, then wait for full deploy before merging this. Drops the legacy night-shift columns now that #114790 has fully deployed and all live code has stopped reading/writing them. - `SafeRemoveField(DELETE)` for `seer_nightshiftrunissue.action`, `seer_nightshiftrun.triage_strategy`, and `seer_nightshiftrun.error_message` — physically drops the columns from Postgres. - Drops the `db_default` on `kind` (kept in #114790 to keep INSERTs from old replicas valid mid-rolling-deploy). All live code now specifies `kind` explicitly, so the safety net is no longer needed.
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.

Repurposes the existing night-shift result table so it can host more than just agentic triage. No behavior change.
SeerNightShiftRunIssue→SeerNightShiftRunResult(state-only viaSeparateDatabaseAndState+RenameModel; underlying Postgres table keeps the historicalseer_nightshiftrunissuename).kinddiscriminator (with aNightShiftRunResultKindenum) and a per-rowextrasJSON.action,error_message, andtriage_strategydata into JSON (extras) and marks the legacy columnsSafeRemoveField(MOVE_TO_PENDING). Physical drop ships in a follow-up.issues,triageStrategy, anderrorMessagealiases for the existing frontend; newresultskey is the canonical shape going forward.