> Plain-language companion for v0.77.0 implementation.

## v0.77.0 — Correctness Stop-the-Line & DVM Proof Infrastructure

Status: ✅ Released.

### Context

v0.77.0 is the first release of the Assessment-15 Hardening Arc (v0.77.0–v0.80.0).
It implements a set of correctness hard gates that were identified during an
independent audit of the differential view maintenance (DVM) engine.

The release has zero user-visible API changes and no schema migrations.
All changes are correctness fixes, safety assertions, and testing infrastructure.

### What changed

**C-1: TRUNCATE LSN fix**

The TRUNCATE CDC trigger was using `pg_current_wal_lsn()` (the WAL write
position) instead of `pg_current_wal_insert_lsn()` (the WAL insert position).
Inside a transaction, the insert position is always at or ahead of the write
position. When a TRUNCATE and subsequent INSERTs were committed in the same
transaction, the stale write-position LSN could cause the refresh engine to
lose the post-TRUNCATE rows. Fixed.

**C-2: Source-placeholder coverage assertion**

The delta template resolver now verifies that every source OID it was given
has both `__PGS_PREV_LSN_{oid}__` and `__PGS_NEW_LSN_{oid}__` placeholder
tokens in the template. If a token is missing, it means the codegen silently
dropped a source table from the delta SQL — which would cause the stream table
to miss changes from that source. The resolver now returns an error that
triggers a full reinitialisation.

**C-3/DVM-1: q12-like CASE/IN-list drift → forced FULL fallback**

TPC-H query 12 uses `SUM(CASE WHEN ... THEN 1 ELSE 0 END)` combined with
`l_shipmode IN ('MAIL', 'SHIP')` in the WHERE clause. This pattern produces
non-deterministic incremental results in the current DVM engine (the delta
rule double-counts rows under certain orderings). v0.77.0 detects this pattern
and forces a FULL refresh with reason code `CASE_IN_LIST_DVM_DRIFT_FULL_FALLBACK`.
The root-cause fix (correct delta rule for CASE aggregates) is planned for v0.78.0.

**DVM-2/P-1: q20-like correlated aggregate subquery → forced FULL fallback**

TPC-H query 20 contains `ps_availqty > (SELECT 0.5 * SUM(l_quantity) FROM lineitem WHERE ...)`.
In the DVM delta SQL, this inner aggregate subquery is re-evaluated for every
changed row, giving O(delta × table) complexity. At SF=10 this produces
delta SQL that takes 45+ minutes per cycle. v0.77.0 detects this pattern
(comparison operator + aggregate subquery) and forces a FULL refresh with
reason code `CORRELATED_SUBQUERY_DELTA_QUADRATIC`. The root-cause fix
(pre-aggregation CTE rewrite) is planned for v0.78.0.

**D-1: Per-source advisory lock in cleanup**

When two stream tables share a source table, two concurrent refresh workers
can both enter `drain_pending_cleanups` for the same source OID in the same
tick. The min-frontier computation + DELETE/TRUNCATE must be atomic per source.
v0.77.0 adds `pg_try_advisory_xact_lock(oid::bigint)` — a non-blocking,
transaction-scoped lock — to guarantee exactly one worker owns the cleanup
window per source OID per transaction.

**DVM-3: `pg_trickle.validate_delta_invariants` GUC**

New boolean GUC, default `false`. When enabled, after every successful
DIFFERENTIAL refresh the extension compares the stream table's row count
against a full recomputation of the defining query. A mismatch emits a WARNING.
Intended for CI pipelines and debugging; the performance impact is significant
(runs the full query after every differential).

**C-4: Semgrep CI rule (formalised)**

The existing `rust.panic-in-sql-path` semgrep rule in `.semgrep/pg_trickle.yml`
already blocks `.unwrap()`, `.expect()`, and `panic!()` in non-test code on
every PR. v0.77.0 formally annotates it as the C-4 Assessment-15 hard gate.

**T-1: DVM algebra property generators**

Added 12 property-based unit tests in `src/refresh/tests.rs` covering
`classify_case_in_list_aggregate_drift` and
`classify_correlated_aggregate_subquery_in_where`. Tests verify canonical
true-positive patterns (q12, q20), variant patterns (lowercase, `>=`, `<`),
and false-positive guards (benign aggregates, simple scans).

**T-4: TRUNCATE LSN E2E regression tests**

Added two E2E tests in `tests/e2e_cdc_tests.rs` verifying the C-1 fix:
1. TRUNCATE + INSERT in the same transaction: only post-TRUNCATE rows survive.
2. TRUNCATE then INSERT in separate transactions: same correctness guarantee.

**D-2: IMMEDIATE mode SAVEPOINT/rollback E2E tests**

Added three E2E tests in `tests/e2e_v077_tests.rs` verifying that IMMEDIATE
mode stream tables correctly handle transaction rollbacks:
1. Rolling back a SAVEPOINT leaves no ghost rows.
2. Partial SAVEPOINT rollback: committed rows visible, rolled-back rows absent.
3. Nested SAVEPOINTs: rolling back to outer SAVEPOINT discards all inner work.

### Upgrade notes

No action required. The upgrade SQL (`pg_trickle--0.76.0--0.77.0.sql`) is a
no-op — there are no catalog changes. The binary upgrade is safe to apply
with zero downtime using `ALTER EXTENSION pg_trickle UPDATE`.
