Files
portfolio-hub/docs/batches/bat-025_20260715_portfolio-ledger-alembic-migration/verification.md
T

6.2 KiB

BAT-025 Developer Self-Verification

  • Status: release-candidate — PR #21 independent QC PASS; lead confirmation recorded
  • Batch: BAT-025
  • Requirement: REQ-057
  • Date: 2026-07-15
  • Scope boundary: local isolated PostgreSQL evidence only. No production DB, deployment, service activation, push, merge, or release action was performed.

Acceptance mapping

REQ-057 acceptance area Evidence Result
Explicit 0028 revision is the chain head alembic_version queried in a throwaway PostgreSQL DB after upgrade Pass — current revision 20260715_0028
Existing broker/manual business data survives upgrade Real 20260628_0027 → head upgrade after a representative pre-existing ledger row is inserted; row fields and metadata are asserted after upgrade Pass
source is backfilled/defaulted/not-null Real upgrade asserts preserved row source='broker'; schema inspection checks text type, non-null constraint, and default Pass
Runtime-precreated metadata schema converges Real test creates all four columns with nullable source, invokes bootstrap, and asserts source backfill/default/not-null plus current=head Pass
Representative broker/manual writes still work Post-upgrade synthetic repository writes assert broker source and manual metadata fields Pass
Earlier fresh PostgreSQL chain can reach 0028 0025 identity-column PostgreSQL incompatibility corrected and exercised by fresh throwaway DB migration path Pass
API/manual-ledger regression tests/test_v1_portfolios_manual_ledger.py, tests/test_v1_portfolios_trades.py, tests/test_v1_portfolios_ledger.py Pass — 33 tests
Whole-repository regression pytest with project dev extra plus temporary TestClient dependency overlay Pass — 597 tests, 11 warnings
Lint/compile/diff hygiene Ruff, compileall, git diff --check Pass

Executed commands and results

  • BAT025_LOCAL_POSTGRES_DSN=[REDACTED local loopback maintenance DSN] PYTHONPATH=. uv run --extra dev --with httpx2 python -m pytest -q --override-ini addopts='' -p no:cacheprovider tests/test_bat025_portfolio_ledger_manual_metadata_migration.py
    • 3 passed in 6.10s.
    • Each test creates and removes a UUID-named database on local loopback PostgreSQL; it refuses non-loopback hosts and non-postgres maintenance databases.
  • PYTHONPATH=. uv run --extra dev --with httpx2 python -m pytest -q --override-ini addopts='' -p no:cacheprovider
    • 597 passed, 11 warnings in 41.41s.
    • Warnings are Starlette deprecations for HTTP_422_UNPROCESSABLE_ENTITY; they are not BAT-025 failures.
  • uv run --extra dev ruff check app/db/migrations.py migrations/env.py migrations/versions/20260605_0025_ledger_consolidation.py tests/test_bat025_portfolio_ledger_manual_metadata_migration.py
    • All checks passed.
  • python3 -m compileall -q app migrations and git diff --check
    • exit 0.

Evidence boundaries and blockers

  • The local container is an isolated test target, not a staging or production database.
  • No production backup/restore, lock-duration measurement under production load, migration run against an operational DB, deploy, or service activation was attempted.
  • The test command uses a transient httpx2 overlay because this environment's resolved Starlette TestClient requires it while the project declares httpx; no dependency source change was made for this batch.
  • The initial independent QC reproduced the technical evidence but returned FAIL because the then-committed document described the remediation as uncommitted and its test run produced an untracked uv.lock. Follow-up commit 71a0312e1efb54772b94fd7de0d8add5943f05af corrected provenance/hygiene only; independent re-QC inspected that committed diff and passed it.

PR #21 provenance reconciliation

The delivery was implemented and initially verified on the isolated worktree chain. PR #21 was then assembled by cherry-picking that chain onto the confirmed local-main baseline, which created different commit IDs. The mappings are:

Original worktree commit PR #21 commit Purpose
f6195ff8090d8761d467e15f44255642ca350e80 1909caa22ce3f7d271dfb619b9095f998d0566cc BAT-025 implementation
779d6f7711d700d6f56be22023cb826cc6f2fe28 d48279f7abdbabe1eb59a8d85703cf21f28d39d0 PostgreSQL verification hardening
71a0312e1efb54772b94fd7de0d8add5943f05af 2f82251e57cfefacec3dd39c49bfe40d605fe145 provenance/hygiene correction
da731b554a2cb7823100f32c85e8cab578e0ea36 5f8097947c1933f6b5eadeab94e5528680effc10 lead confirmation state at PR creation
  • git diff --exit-code da731b55..5f809794 confirmed that the original verified worktree state and PR #21 initial head have identical file content.
  • Lead reproduction after the PR QC environment correction used the tracked local-test loopback defaults without exposing the DSN. The migration suite passed 3 passed in 6.16s.
  • Cleanup verification targets only the fixture contract portfolio_hub_bat025_<32 lowercase hex UUID>; its catalog count was 0. The separately existing portfolio_hub_bat025_test database does not match that generated-name contract and was not modified.

Gate result

  • Developer self-verification: complete on the original worktree remediation chain, with the PR #21 commit mapping above.
  • Initial independent QC: FAIL — documentation provenance and untracked uv.lock hygiene only; technical ACs reproduced.
  • Original-worktree independent re-QC: PASS (deleg_6b805aa0, 2026-07-15), including loopback PostgreSQL and direct Ruff evidence.
  • PR #21 committed-diff QC: PASS (deleg_ae0c6f27, 2026-07-15). It verified the cherry-pick patch-id mapping, PR head bd51330, migration semantics, loopback PostgreSQL suite (3 passed), fixture-generated UUID catalog cleanup (0), direct Ruff checks, clean tested worktree, and PR diff hygiene.
  • confirm-batch-verification: PASS accepted by TREX lead (2026-07-15). This approval is limited to merging the verified PR; it does not authorize release, deployment, operational database migration, or service restart.
  • M5 Release: not started. Release preparation requires separate scope/approval after merge; production migration requires a separate operational decision and release approval.