Skip to content

Register the event-slug data migration in the isolation inventory #295

Description

@alexeygrigorev

Product outcome

Restore the deterministic data-migration isolation gate after the accepted event-slug shortening added a historical RunPython migration without registering it in the gate's exact inventory. The gate must discover and inspect that migration like every other data migration, while event rows, aliases, canonical URLs, slug allocation, and migration execution remain byte-for-byte behaviorally unchanged.

Confirmed evidence

  • Exact failed release anchor: face8e4808d65afbf0374d1ced7a88079950d663.
  • Scheduled run 33315212334, migrations job 99267303151 ran make test-migrations and failed MigrationSeedContractTests.test_every_data_migration_uses_historical_apps_without_runtime_side_effects because the discovered set contained one unregistered path: events/migrations/0012_shorten_event_slugs.py.
  • Commit ef19e48 added that migration. It uses historical apps.get_model("events", "Event") and apps.get_model("events", "EventAlias"), performs deterministic ordered database updates, and imports no current application model/service.
  • test_support/tests/test_migrations.py maintains an exact allowlist of every file for which data_migration_functions() finds a RunPython callable. It then runs assert_data_migration_isolation(path) and requires the source to contain apps.get_model for every registered path. The new migration is discovered correctly; only the expected inventory entry is absent.
  • The same CI job separately fails EditorialRouteMigrationContractTests.test_checked_manifest_is_bound_to_schema_projection_and_runtime on a projection digest mismatch. That failure belongs to Reconcile non-reproducible public projection after face8e4 #253 and is not part of this issue.
  • Repository and GitHub issue search found no existing owner for the missing 0012_shorten_event_slugs.py inventory entry. Restore face8e4 formatting, typing, and focused content gates #261 owns a bounded formatting/typing/template recovery and does not include this file or failure.

Normative authority

Scope

Change exactly one tracked file:

  • test_support/tests/test_migrations.py

Add events/migrations/0012_shorten_event_slugs.py exactly once to the expected data-migration path set in test_every_data_migration_uses_historical_apps_without_runtime_side_effects. Retain exact-set equality so both an unreviewed new data migration and a stale/nonexistent inventory entry continue to fail closed.

The existing loop must then apply the existing isolation checker and historical-apps.get_model source assertion to migration 0012; do not special-case, skip, mock, or weaken either check.

Acceptance criteria

  • The exact expected data-migration inventory contains events/migrations/0012_shorten_event_slugs.py once, in the established deterministic ordering, with no other inventory membership change.
  • The focused inventory test discovers migration 0012 through the existing AST-based RunPython detection and runs the same assert_data_migration_isolation and apps.get_model requirements used for every other data migration.
  • Removing the new inventory entry reproduces the exact unexpected-path failure; adding an unregistered synthetic numbered RunPython migration or a stale expected path still fails exact-set equality. No permissive glob-only assertion replaces the reviewed inventory.
  • events/migrations/0012_shorten_event_slugs.py, events/slugs.py, event models/services/routes/templates/projections/manifests, and event tests are unchanged by this issue.
  • Existing migration 0012 semantics remain unchanged: historical models only, deterministic id ordering, current slug/alias update behavior, no network/provider/runtime-model import, and the existing no-op reverse operation.
  • The exact focused Django test passes on the frozen candidate. After Reconcile non-reproducible public projection after face8e4 #253 repairs the independent editorial projection digest mismatch, make test-migrations passes in full with 18 tests and no skip, retry, xfail, quarantine, assertion weakening, or accepted residual failure.
  • Locked format/lint/type/migration-drift checks and the graph-selected versioned verification plan/report pass on the same frozen candidate.
  • Engineer and independent tester publish their exact base/candidate, one-file diff digest, plan/report digests, terminal commands/counts, and confirm the event product surface is unchanged.

Required test scenarios

  1. Run the exact focused test:
    uv run --frozen python manage.py test --noinput test_support.tests.test_migrations.MigrationSeedContractTests.test_every_data_migration_uses_historical_apps_without_runtime_side_effects.
  2. Prove migration 0012 is in the discovered set and is evaluated by both existing historical-isolation assertions, without changing the migration source.
  3. Prove the contract remains fail-closed for one unexpected numbered RunPython migration and one stale expected path using the smallest existing test technique; do not leave a synthetic migration in the repository.
  4. On a base containing Reconcile non-reproducible public projection after face8e4 #253's accepted projection repair, run make test-migrations and require all 18 tests green. A run that still contains Reconcile non-reproducible public projection after face8e4 #253's unrelated digest failure is useful attribution evidence but is not terminal tester acceptance.
  5. Run the change-selective plan and every selected repository/Django gate. Browser execution and screenshots are not_applicable only if the final one-file diff proves no render-impact path changed.

Dependencies and recovery ordering

There is no implementation dependency on #253 or #261: an engineer may prepare and freeze this one-file correction independently from the exact face8e4 anchor. It does not overlap #261's allowed files and must not be folded into or mutate the already frozen #261 candidate.

Final tester acceptance and integration do require a clean shared migration component. #253 owns the second, independent make test-migrations failure and must supply its accepted repair before this issue can claim the full target green. Preserve the recovery order already assigned to #261; rebase this candidate after the accepted #253/#261 recovery base and land it immediately after them, before later recovery issues reuse or claim migration-component evidence. Any base or source change invalidates the versioned plan and requires recomputation.

Non-goals

  • No edit to events/migrations/0012_shorten_event_slugs.py, event data, aliases, slug length/allocation, routes, redirects, public copy, visual design, or event behavior.
  • No new migration, seed, reverse migration, data replay, database/provider/production access, or durable job.
  • No Reconcile non-reproducible public projection after face8e4 #253 projection/source/pin/manifest/hash/terminology repair and no generated artifact change.
  • No Restore face8e4 formatting, typing, and focused content gates #261 formatting, archive-row, normalization, or prose-template work.
  • No refactor of data_migration_functions, assert_data_migration_isolation, the migration test suite, Make targets, CI workflow, tool version, or verification policy.
  • No assertion weakening, broad exception, skip, retry, xfail, quarantine, timeout increase, test deletion/demotion, commit, push, merge, or deployment during engineering/testing.

Verification disposition

This is an internal migration-test contract correction with no product render impact. Playwright and screenshots are not_applicable only for the exact one-file final diff; the independent tester must confirm that disposition from the recomputed graph. The ordinary engineer → independent tester → PM acceptance → focused commit → local no-ff merge/push → on-call lifecycle still applies.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P0Must-have or release-blockingbugSomething isn't workingdata-migrationArea: data-migrationeventsArea: eventstestingArea: testing

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions