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
+12 -12
View File
@@ -16,18 +16,18 @@
//!
//! ADR-0019 §6 calls for re-querying the database after a
//! constraint failure to surface the offending row(s) through
//! ADR-0017's bordered diagnostic-table renderer. That layer
//! is plumbed structurally — [`FriendlyError::diagnostic_table`]
//! exists for it — but the actual re-query implementation is a
//! separate commit alongside its runtime-side wiring (the
//! translator needs the user's attempted values, which arrive
//! through [`TranslateContext`] populated at the runtime
//! callsite).
//!
//! For now, [`FriendlyError::diagnostic_table`] is always
//! `None` and the wording carries the full burden. Adding the
//! diagnostic table later is purely additive: the translator's
//! catalog keys and the renderer don't change.
//! ADR-0017's bordered diagnostic-table renderer. This is
//! **implemented** (commit `431645a`): the *runtime* resolves the
//! schema-dependent facts — table/column, parent/child tables, the
//! attempted value, and any pinpointed rows — into a
//! [`FailureContext`], which [`TranslateContext::from_facts`] feeds
//! into the translator. When those facts carry a pinpoint,
//! [`FriendlyError::diagnostic_table`] is populated and the renderer
//! appends the bordered table; when they don't (no live DB handle,
//! re-query failed, or a fallback callsite), it stays `None` and the
//! catalog wording carries the full burden. The translator itself
//! never touches the database — it only renders the facts it is
//! handed — so the two layers stay cleanly separable.
use crate::db::{DbError, SqliteErrorKind};
use crate::dsl::Type;