docs: mark H1 done — friendly DB-error layer is shipped

Verification found H1 (ADR-0019) fully implemented and tested: the
friendly::translate_error chokepoint is wired on the live failure path
(runtime + app + DbError::friendly_message), covers all five error
categories (UNIQUE, FOREIGN KEY both sides, NOT NULL, CHECK,
type-mismatch) with operation×kind×verbosity wording, the messages
verbosity command, and §6 row-pinpointing via runtime-resolved facts —
backed by 44 friendly unit tests + 12 full-stack friendly_enrichment
integration tests. The "partial / FK-only" notes were stale.

Mark requirements H1 done; fix the obsolete "diagnostic_table is
always None" comment in translate.rs (pinpointing landed in 431645a).
Remaining ADR-0019 scope (§9 i18n sweep, §OOS-2 advanced-SQL
sanitization, §OOS-3 messages persistence) stays deferred.
This commit is contained in:
claude@clouddev1
2026-06-02 20:07:45 +00:00
parent 56d9671488
commit be7b078878
2 changed files with 27 additions and 18 deletions
+15 -6
View File
@@ -542,12 +542,21 @@ since ADR-0027.)
## Hints, help, errors ## Hints, help, errors
- [ ] **H1** Friendly error-rewriting layer translates SQLite - [x] **H1** Friendly error-rewriting layer translates engine
error messages into learner-friendly equivalents. error messages into learner-friendly equivalents (ADR-0019).
*(Progress: foreign-key constraint failures are enriched *(Done: the `friendly::translate_error` chokepoint is wired on
with both inbound and outbound relationship listings (so the live failure path (runtime + app + `DbError::friendly_message`)
RESTRICT errors point at the children that still reference and covers all five ADR-0019 §3 categories — UNIQUE, FOREIGN KEY
this table); full SQL → English translation pending.)* (parent- and child-side), NOT NULL, CHECK, and type-mismatch —
with operation×kind×verbosity catalog wording, the
`messages short|verbose` verbosity command, and §6 row-pinpointing
via runtime-resolved facts rendered through the bordered
diagnostic table. Covered by 44 `friendly` unit tests + 12
full-stack `friendly_enrichment` integration tests. Remaining
ADR-0019 scope is deferred and separately tracked: the §9 i18n
migration sweep of all other user-facing strings, advanced-mode
SQL-error sanitization (§OOS-2), and `messages` persistence
(§OOS-3, awaits the settings ADR).)*
- [ ] **H1a** Strong syntax-help in parse errors. When the user - [ ] **H1a** Strong syntax-help in parse errors. When the user
types something near-correct (e.g. `insert into T ('Oli')` — types something near-correct (e.g. `insert into T ('Oli')` —
forgotten `values`; or `update T set x=1` — missing WHERE), forgotten `values`; or `update T set x=1` — missing WHERE),
+12 -12
View File
@@ -16,18 +16,18 @@
//! //!
//! ADR-0019 §6 calls for re-querying the database after a //! ADR-0019 §6 calls for re-querying the database after a
//! constraint failure to surface the offending row(s) through //! constraint failure to surface the offending row(s) through
//! ADR-0017's bordered diagnostic-table renderer. That layer //! ADR-0017's bordered diagnostic-table renderer. This is
//! is plumbed structurally — [`FriendlyError::diagnostic_table`] //! **implemented** (commit `431645a`): the *runtime* resolves the
//! exists for it — but the actual re-query implementation is a //! schema-dependent facts — table/column, parent/child tables, the
//! separate commit alongside its runtime-side wiring (the //! attempted value, and any pinpointed rows — into a
//! translator needs the user's attempted values, which arrive //! [`FailureContext`], which [`TranslateContext::from_facts`] feeds
//! through [`TranslateContext`] populated at the runtime //! into the translator. When those facts carry a pinpoint,
//! callsite). //! [`FriendlyError::diagnostic_table`] is populated and the renderer
//! //! appends the bordered table; when they don't (no live DB handle,
//! For now, [`FriendlyError::diagnostic_table`] is always //! re-query failed, or a fallback callsite), it stays `None` and the
//! `None` and the wording carries the full burden. Adding the //! catalog wording carries the full burden. The translator itself
//! diagnostic table later is purely additive: the translator's //! never touches the database — it only renders the facts it is
//! catalog keys and the renderer don't change. //! handed — so the two layers stay cleanly separable.
use crate::db::{DbError, SqliteErrorKind}; use crate::db::{DbError, SqliteErrorKind};
use crate::dsl::Type; use crate::dsl::Type;