Generalises serial and shortid beyond their previous restricted
forms:
- `serial` is no longer restricted to single-column PK. Non-PK
serial columns get an emitted UNIQUE constraint and use
application-side MAX(col)+1 at INSERT time (rowid alias still
drives the PK case for free; per ADR-0010 worker-thread
serialisation, the read-then-insert sequence is safe).
- `shortid` columns auto-fill existing null cells when the
column is materialised — `add column T: x (shortid)` on a
non-empty table no longer leaves rows in a not-really-valid
NULL state.
- `int -> serial` joins the type-change matrix as always-clean
identity (closes the asymmetry vs `text -> shortid`); other
sources are refused with a route-via-int hint.
- `change column T: x (serial|shortid)` fills null source
cells with sequence / generated values in the same rebuild
transaction.
Internal infrastructure:
- ReadColumn gains `unique: bool`; read_schema detects single-
column UNIQUE indexes via pragma_index_list /
pragma_index_info; schema_to_ddl emits inline UNIQUE for
non-PK columns.
- ColumnSchema (persistence) gains `unique: bool` so the flag
survives YAML round-trip and rebuild-from-text reconstructs
it faithfully — preserves the "serial -> int leaves UNIQUE
in place" promise across save/load cycles.
- ChangeColumnTypeResult.client_side now carries `auto_filled`
+ `auto_fill_kind` alongside `transformed` + `lossy`; the
app handler renders separate note lines when both apply.
- AddColumnResult is a new return type carrying pre-rendered
[client-side] note lines for the auto-fill paths.
Tests: 519 -> 534 (+15). Clippy clean.
Replaces the placeholder "trust STRICT" body of do_change_column_type
with the per-cell transformer matrix from ADR-0017. Adds:
- src/type_change.rs: CellOutcome { Clean / Lossy / Incompatible }
+ transform_cell + static_refusal covering every matrix pair
from §3 (54 unit tests).
- --force-conversion and --dont-convert flags on `change column`
(mutually exclusive at parse time per §5).
- Refined PK rule (§4.1): refused only when the column has an
inbound FK and fk_target_type would change. Outbound-FK columns
still refused outright (§4.2). PK / shortid uniqueness checked
post-transformation (§4.3).
- Bordered diagnostic tables (lossy / incompatible / collision)
via the pretty-table renderer (§7) — uses ADR-0016's primitives.
- [client-side] success note (§6) when any cell was rewritten.
- Friendly wrapper for engine-level errors under --dont-convert
so no engine vocabulary leaks (ADR-0002 user-facing posture).
ADR-0017 §3 + §7 amended in place (with user sign-off): serial->int
added explicitly to the always-clean matrix, and diagnostic rows
identify themselves by PK value(s) rather than positional indices
(SQLite returns rows unordered without ORDER BY, so positional
"row 5" is unaddressable).
Tests: 449 -> 517 (+68). Clippy clean with nursery lints.