Skip to content

feat(states): add TaskStateORM and task_states table migration - #391

Draft
vineetvora-scale wants to merge 3 commits into
mainfrom
vineetvora/task-state-orm-and-table
Draft

feat(states): add TaskStateORM and task_states table migration#391
vineetvora-scale wants to merge 3 commits into
mainfrom
vineetvora/task-state-orm-and-table

Conversation

@vineetvora-scale

@vineetvora-scale vineetvora-scale commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Summary

Second PR in the task-state storage series (follows #380). Adds TaskStateORM and a migration creating the task_states table: the PostgreSQL home for task state once the Postgres repository lands in the next PR.

The table is created empty and inert. Nothing reads or writes it until the repository PR wires the postgres phase, so deploying this changes no behavior. The migration is schema-only on a brand-new table (instant, no locks against live traffic) and downgrade cleanly drops it.

Deliberately deferred (needs design sign-off)

Two decisions from the design review are still open, so this PR ships without them and stays in draft until they close:

  1. The (task_id, agent_id) index/constraint is absent. Its shape is the open write-semantics decision: a unique constraint backing an atomic upsert, or a plain compound index mirroring MongoDB's non-unique one. It ships alongside the repository that implements whichever contract is chosen.
  2. FK delete behavior (proposed). Both FKs are bare, no ON DELETE action, matching the repo convention. Rationale: MongoDB has no cascades, so state deletion is application-driven on both backends and a Postgres-only cascade would be a silent behavioral divergence; the FK alone prevents orphaned rows, and a future hard-delete flow should remove states through the repository or fail loudly on the constraint. This is Q5 in the TDD, deliberately left open for input; chime in there or here if you see a case for CASCADE.

Verification

  • Migration linter clean; ruff clean; full unit suite passes (the ORM materializes in the test fixtures' Postgres containers).
  • Applied the full migration chain from scratch against a disposable Postgres 17 container: table shape verified column for column, downgrade removes it cleanly, re-upgrade succeeds.

What's next

The final M1 PR: TaskStatePostgresRepository implementing the repository contract from #380, the selector's postgres branch going live, and the parity test suite running against both backends.

Empty, inert table: nothing reads or writes it until the Postgres
task-state repository lands. The (task_id, agent_id) index is deferred
to the write-semantics decision.
MongoDB has no cascades, so state deletion is application-driven on both
backends; a Postgres-only cascade would diverge silently on a future task
hard-delete. The FK alone prevents orphaned rows.
DELETE /tasks issues a real row delete today and already fails on the
sibling child tables' bare FKs; the earlier comment implied no hard-delete
path exists. Also warn that explicitly-None timestamps bypass the server
default and violate NOT NULL.
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