One-time, mechanical reformat — no functional changes. The tree was not
rustfmt-clean (~1800 hunks across ~100 files); this brings it to stock
`cargo fmt` defaults so a `cargo fmt --check` CI gate can follow.
Behaviour-preserving: 2509 pass / 0 fail / 1 ignored (unchanged baseline),
clippy clean. A .git-blame-ignore-revs entry follows so `git blame`
skips this commit.
Completes the i18n sweep started in the previous commit. All
remaining hand-rolled user-facing English strings inside
thiserror #[error(...)] attributes have been moved into the
catalog. Drops the thiserror dependency entirely.
Twelve error types migrated:
- dsl::action::UnknownAction → parse.custom.unknown_action
- dsl::parser::ParseError → parse.error_wrapper + parse.empty
- dsl::value::ValueError → value.{type_mismatch,format}
- persistence::csv_io::CsvError → persistence.csv.*
- persistence::mod::PersistenceError → persistence.{io,encode}
- persistence::yaml::YamlError → persistence.yaml.*
- persistence::migrations::MigrateError → persistence.migrate.*
- project::lock::LockError → project.lock.*
- project::naming::NamingError → project.naming.*
- project::naming::UserNameError → project.user_name.*
- project::mod::ProjectError → project.{path_not_found,...}
- project::mod::SafeDeleteError → project.safe_delete.*
- archive::ArchiveError → archive.*
- cli::ArgsError → cli.*
- db::DbError → db.error.*
Pattern per type: drop thiserror::Error derive, write manual
Display calling crate::t!(), keep #[from] semantics via
explicit From impls, override Error::source() where applicable
so #[source]-style chaining is preserved.
Why this matters (user rationale): "fine to have fallbacks for
errors that are purely technical, but lift the output to a
place where it can be localized later and where an adjustment
with friendly text is easily possible if any of them become
part of the happy path." All surface strings now live in
en-US.yaml and can be reworded or localized without touching
Rust source.
Tests: 769 passing, 0 failed, 1 ignored. Clippy clean with
-D warnings. Cargo.toml: drop thiserror = "2.0.18".
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.
DSL data operations (ADR-0014):
- insert into T [(cols)] values (vals); short form
insert into T (vals) omits values keyword for friendlier
syntax.
- update T set ... where col=val | --all-rows; delete from T
where col=val | --all-rows; show data T.
- Value AST (Number/Text/Bool/Null) with per-column-type
validation in the executor: int/real/decimal/bool/date/
datetime/shortid each accept a documented literal shape
and produce friendly format errors naming the column.
- INSERT short form fills non-auto-generated columns in
schema order; auto-fills serial via SQLite and shortid
via the new generator (T2).
- `add column [to table] T: c (type)` -- `to table` now
optional.
Database:
- insert/update/delete via prepared statements with bound
rusqlite::types::Value parameters.
- InsertResult/UpdateResult/DeleteResult: writes return
rows_affected plus the affected row(s) only (not the whole
table), so users see exactly what changed.
- INSERT shows the just-inserted row via last_insert_rowid.
- UPDATE captures matching rowids up-front and fetches them
post-update -- works even if the UPDATE changed the WHERE
column.
- DELETE reports per-relationship cascade effects by row-
count diffing inbound child tables; UPDATE-side cascades
are not yet detected (would need value diffing).
- query_data formats cells (booleans true/false, NULLs as
None).
FK error enrichment:
- Now lists both outbound (INSERT/UPDATE relevance) and
inbound (DELETE/UPDATE on parent relevance) FKs from the
metadata, so RESTRICT errors point at the children
blocking the delete.
- RelationshipSelector has a proper Display impl -- "no
such relationship" reads cleanly.
Relationship display:
- target_table for AddRelationship/DropRelationship now
returns the parent (1-side); structure rendering after
add/drop shows that side's "Referenced by:" entry,
matching the `from <Parent>` direction of the command.
- [ok] summary uses display_subject so relationship
commands show both endpoints (`from P.col to C.col`)
rather than a single misleading table name.
- Auto-name format `<Parent>_<pcol>_to_<Child>_<ccol>`
(matches the from..to direction).
Output rendering and scrolling:
- Wrap-aware scroll: renderer reports both visible-row
count and total wrapped-row count to App; scroll math
caps against actual displayable rows. Long lines wrap;
the bottom line is always reachable; PageUp/PageDown work
correctly even after paging past the buffer top.
- Multi-line messages (FK error enrichment, cascade summary)
split into single-line OutputLines at creation time so
wrap/scroll math agree.
Runtime / events:
- New AppEvent variants for Insert/Update/Delete success
carrying typed result structs; DslDataSucceeded reserved
for show-data queries.
Docs:
- ADR-0014 covers data-op grammar, value model, --all-rows
safety, auto-show.
- requirements.md: C5 done, T2 done, V2 partial (basic data
view), V5 partial (show data added). New entries: C5a
complex WHERE expressions; H1 progress note for FK
enrichment; H1a (strong syntax-help in parse errors).
Tests: 200 passing (183 lib + 17 integration), 0 skipped.
Includes parser, type-validation, DB write/read, FK-failure
enrichment, cascade-delete propagation, focused-auto-show
behaviour, scroll-cap invariants. Clippy clean with nursery
enabled.