Skip to content

Plan: Implement repository contracts and Alembic migrations (2.6.2) - #142

Draft
leynos wants to merge 2 commits into
mainfrom
2-6-2-repository-contracts-and-alembic-migrations
Draft

Plan: Implement repository contracts and Alembic migrations (2.6.2)#142
leynos wants to merge 2 commits into
mainfrom
2-6-2-repository-contracts-and-alembic-migrations

Conversation

@leynos

@leynos leynos commented Jun 15, 2026

Copy link
Copy Markdown
Owner

Summary

This is a planning PR. It carries the execution plan for roadmap item
2.6.2 — Implement repository contracts and Alembic migrations and is
intended for review of the plan before any implementation begins. The plan is
in DRAFT status and must be approved before code is written.

The execplan lives at
docs/execplans/2-6-2-repository-contracts-and-alembic-migrations.md.

It supersedes the initial draft on this branch, which was written without
inspecting the codebase (it invented port signatures and a module path that do
not exist, and cited a stale base migration revision). The replacement is
grounded in the real 2.6.1 contracts, prior art, and a community-of-experts
design review.

What the slice will deliver

2.6.1 already defined the generation-run domain model and the composite
GenerationRunPort (in episodic/canonical/generation_run_ports.py) with an
in-memory reference adapter. This slice adds the durable layer behind that port:

  • A PostgreSQL-backed SqlAlchemyGenerationRunStore implementing the existing
    composite port, wired into SqlAlchemyUnitOfWork as uow.generation_runs.
  • An Alembic migration creating generation_runs, generation_events, and
    generation_checkpoints, chained off the current head 20260601_000009.
  • Integration tests validating event ordering, plus parametrised port-contract
    tests run against both the in-memory and PostgreSQL adapters.

Key design decisions (see the execplan Decision Log)

  • Per-run event seq allocated as MAX(seq)+1 under
    UNIQUE(generation_run_id, seq) with a bounded retry inside a savepoint and a
    conflict metric — mirroring the established history-table revision pattern;
    a global Postgres sequence is rejected (gap/visibility problems).
  • seq stored as BIGINT; composite indexes for list_runs; explicit FK
    ON DELETE semantics (events/checkpoints CASCADE, episode RESTRICT); an
    updated_at trigger matching the workflow_checkpoints precedent.
  • create_run idempotency via a unique idempotency_key column (first-write-wins).
  • Behavioural equivalence with the in-memory adapter is claimed only under the
    single-writer-per-run assumption; the py-pglite single-connection limitation
    and a follow-up real-PostgreSQL concurrency test are documented.

Testing approach

Red-Green-Refactor with pytest unit tests, py-pglite integration tests for event
ordering, and bounded Hypothesis property coverage for the sequence invariant.
vidai-mock is out of scope: this slice performs no inference. All gates
(make check-fmt, make typecheck, make lint, make test,
make check-migrations, make markdownlint) must pass, followed by a
coderabbit review --agent pass, at each milestone.

References

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @leynos, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 80121c31-a4ac-4010-bf03-2fb834208295

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 2-6-2-repository-contracts-and-alembic-migrations

Comment @coderabbitai help to get the list of available commands and usage tips.

@leynos
leynos force-pushed the 2-6-2-repository-contracts-and-alembic-migrations branch from 44c0ff3 to 83ad969 Compare June 15, 2026 20:23
codescene-delta-analysis[bot]

This comment was marked as outdated.

…rations

This plan defines the scope, stages, and validation criteria for implementing
repository contracts and Alembic migrations for generation-run aggregates.
The plan covers:

- Verification of domain model from 2.6.1
- Definition of GenerationRunRepository and GenerationEventRepository protocols
- Alembic migration for generation_runs and generation_events tables
- SQLAlchemy ORM models and repository implementations
- Integration tests validating event ordering and persistence semantics
- Validation that all gates pass (check-fmt, typecheck, lint, test)

The plan is structured as 8 stages with explicit go/no-go validation points.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
@leynos
leynos force-pushed the 2-6-2-repository-contracts-and-alembic-migrations branch from 83ad969 to ec1cfc1 Compare June 15, 2026 20:26
codescene-delta-analysis[bot]

This comment was marked as outdated.

Replace the initial generation-run persistence execplan, which was
drafted without inspecting the codebase, with a version grounded in the
actual 2.6.1 contracts, prior art, and a community-of-experts design
review.

Corrections over the previous draft:

- Target the real ports in `episodic/canonical/generation_run_ports.py`
  (`create_run`, `get_run`, `list_runs`, `update_run_status`,
  `append_event`, `list_events`, and the checkpoint methods) rather than
  inventing `GenerationRunRepository.add`/`by_id` in a non-existent
  `episodic/generation/ports.py`. The ports already exist; this slice
  implements a PostgreSQL adapter for them.
- Chain the migration off the true head `20260601_000009`, not the stale
  `20260508_000008`, and note the single linear head despite two
  `000009` files.
- Mirror established storage patterns: `Base` declarative models, the
  history-table `UNIQUE(parent_id, seq)` + `CHECK (seq >= 1)` sequence
  pattern, `_RepositoryBase`, per-feature mappers, and `SqlAlchemyUnitOfWork`
  wiring.

Design decisions added after the Logisphere panel (proceed-with-conditions):

- Allocate per-run event `seq` as `MAX(seq)+1` under a unique constraint
  with a bounded retry inside a savepoint and a conflict metric, instead
  of escalating on first conflict; reject a global sequence (gaps) and a
  counter column (pattern divergence).
- Widen `seq` to `BIGINT`; add `(episode_id, created_at)` and
  `(episode_id, status, created_at)` indexes; specify deterministic
  `list_runs` ordering and FK `ON DELETE` semantics; add an `updated_at`
  trigger.
- Qualify behavioural equivalence to the single-writer case and document
  the py-pglite single-connection limitation; force the idempotency
  conflict branch in tests.

Status remains DRAFT pending approval before implementation.
codescene-delta-analysis[bot]

This comment was marked as outdated.

@leynos leynos changed the title (2.6.2) Implement repository contracts and Alembic migrations Plan: Implement repository contracts and Alembic migrations (2.6.2) Jun 19, 2026
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