# v0.60.0 — Code Quality, Test Coverage & CI

> **Full details:** [v0.60.0.md-full.md](v0.60.0.md-full.md)

## What's New

v0.60.0 is the third release of the Assessment-Driven Hardening Arc, closing
the code quality, test coverage, correctness, and CI/CD gaps identified in the
v0.57.0 overall assessment
([plans/PLAN_OVERALL_ASSESSMENT_12.md](../plans/PLAN_OVERALL_ASSESSMENT_12.md)).

### QUAL-1: Scheduler Log Level Standardisation (Q-1)

All `log!()` calls in `src/scheduler/dispatch.rs`, `pool.rs`, and
`scheduler_loop.rs` that represent routine state transitions (start dispatch,
acquire execution lock, worker registered) are upgraded to `info!()`.
`warning!()` remains reserved for recoverable errors.  `error!()` is used for
events that require operator attention.  Operators running at the default
`log_min_messages = warning` now see warnings and above with no extra noise;
operators at `log_min_messages = info` get clean, structured progress output.

### QUAL-2: refresh/codegen.rs Function Decomposition (Q-2)

Three functions exceeding 200 lines (`build_bypass_capture_sql`,
`capture_diff_to_table`, and the primary MERGE template builder) are
extracted into a new `src/refresh/sql_fragments.rs` helper module containing
named single-purpose builders: `build_cte_predicate()`,
`build_merge_join_condition()`, `build_content_hash_column()`, and
`build_delta_target_list()`.

### QUAL-3: src/cdc.rs Module Decomposition (Q-3)

`src/cdc.rs` (3 383 lines) is split into four focused sub-modules, mirroring
the v0.55.0 monitor decomposition:

- `cdc/triggers.rs` — trigger creation, trigger SQL builders, column-name
  escaping, statement vs row mode logic
- `cdc/buffer.rs` — change-buffer DDL, compaction, buffer naming helpers
- `cdc/compact.rs` — compaction scheduling, lock-acquisition helpers,
  `CompactionResult` enum
- `cdc/partition.rs` — partition-promotion detection, `should_promote_to_partitioned`

`cdc/mod.rs` retains public SQL-callable functions and re-exports.

### TEST-1: Refresh Orchestrator and Merge Sub-Module Unit Tests (T-1)

New `#[cfg(test)]` blocks cover the pure-logic paths in:

- `src/refresh/orchestrator.rs` — cost-model state machine transitions (cold
  start → diff-preferred → full-preferred → diff-recovery), threshold
  boundary values, and the adaptive scoring formula.
- `src/refresh/merge/columns.rs` and `conflict.rs` — column-list builders and
  conflict-resolution SQL generation.
- `src/refresh/codegen.rs` — new `sql_fragments.rs` helpers each have table-
  driven unit tests.

### TEST-2: CDC Pure-Logic Unit Tests (T-2)

`src/cdc/triggers.rs` and `src/cdc/buffer.rs` gain `#[cfg(test)]` blocks
testing: `cb_col_name()` (reserved-name escaping), `buffer_base_name_for_oid()`
(OID formatting), `build_changed_cols_bitmask_expr()` (column-bitmask SQL
generation), and `should_promote_to_partitioned()` (partition-promotion
classification).

### TEST-3: DDL Hook Classification Unit Tests (T-3)

`src/hooks.rs` gains a `#[cfg(test)]` block with table-driven tests for
each `DdlCommandKind` variant.  Tests cover: ADD COLUMN on a tracked table,
DROP COLUMN, ALTER COLUMN TYPE, RENAME TABLE, CREATE INDEX, and commands on
untracked tables.

### TEST-4: Fixed Sleep Replacement (T-4)

Remaining `tokio::time::sleep()` calls in `tests/e2e_quota_tests.rs`,
`tests/e2e_bgworker_tests.rs`, and `tests/e2e_wal_cdc_tests.rs` are replaced
with `wait_for_*` polling helpers from `tests/common/mod.rs`, continuing the
programme started in v0.53.0.

### TEST-5: Differential Idempotence Proptest (T-5)

A new `proptest!` block in `src/dvm/diff.rs` asserts that refreshing a stream
table twice with the same source rows (written in randomised partition order)
produces identical output.  This validates the idempotence invariant of the
differential engine under arbitrary ingest ordering.

### COR-5: WAL Decoder OID-Based Table Filter (C-5)

The WAL decoder's change-routing filter is changed from string equality on
qualified names to OID equality.  On each poll cycle, the decoder resolves
each tracked source table to its OID via `to_regclass()` and compares against
the decoded row's relation OID (available in the `pg_logical_slot_changes`
record).  Text-name matching is retained only as a fallback when OID lookup
fails.

### COR-6: Publication Rebuild Detects Partition-Attach (C-6)

`check_if_publication_needs_rebuild()` now also detects when a source table
transitions from a standalone table to a partition of another table (i.e.,
when `pg_inherits.inhrelid = source_oid` becomes true).  When this transition
is detected, the WAL publication is rebuilt with `publish_via_partition_root =
true` and the stream table is marked for reinit.

### CI-1: Path-Filtered Full E2E on PRs (CI-1)

`.github/workflows/ci.yml` gains a new `full-e2e-on-dvm-change` job that
runs the full E2E test suite (stock test image, no TPC-H) when a PR modifies
any file under `src/dvm/`, `src/refresh/`, or `src/cdc/`.  This reduces the
worst-case detection window for DVM regressions from ~24 hours to within the
PR merge gate.

### CI-2: Dockerfile.e2e Non-Root User (CI-2)

`tests/Dockerfile.e2e` adds `USER postgres` before the final `CMD`, so test
containers run as the `postgres` system user instead of root.

### CI-3: Codecov Threshold for Safety-Critical Modules (CI-3)

`codecov.yml` adds per-path coverage thresholds for modules previously
excluded from the patch gate: `src/cdc/**` (50%), `src/hooks.rs` (40%),
`src/wal_decoder.rs` (40%).
