feat(hint): H2 Phase D — coverage gate, F1 strip, status flips (ADR-0053)
Completes H2: - comprehensiveness coverage tests: every REGISTRY command form has a hint_id resolving to a hint.cmd.* block, and every runtime error class resolves to a hint.err.* block (enforces ADR-0053 D6) - ADR-0051 keybinding strip advertises F1 in the editing (leads) and default states; +shortcut.hint label; 12 full-panel snapshots re-accepted (status-bar line only) - flip ADR-0053 -> implemented, requirements H2 + A1 -> [x], README 2498 pass / 1 ignored, clippy clean.
This commit is contained in:
@@ -962,6 +962,56 @@ mod hint_key_tests {
|
||||
// Unknown entry word → None (tier-2 fallback).
|
||||
assert_eq!(hint_key_for_input_in_mode("zzz", Mode::Simple), None);
|
||||
}
|
||||
|
||||
/// Comprehensiveness gate (ADR-0053 D6): every command form in the
|
||||
/// REGISTRY carries at least one `hint_id`, and each resolves to a
|
||||
/// tier-3 `hint.cmd.<id>` block. `keys.rs` checks referenced keys
|
||||
/// resolve; this checks every command *has* one.
|
||||
#[test]
|
||||
fn every_command_form_has_a_tier3_block() {
|
||||
let cat = crate::friendly::catalog();
|
||||
for (node, _category) in super::REGISTRY {
|
||||
assert!(
|
||||
!node.hint_ids.is_empty(),
|
||||
"command `{}` has no hint_ids (ADR-0053 D6)",
|
||||
node.entry.primary
|
||||
);
|
||||
for id in node.hint_ids {
|
||||
let key = format!("hint.cmd.{id}.what");
|
||||
assert!(
|
||||
cat.get(&key).is_some(),
|
||||
"missing tier-3 block `{key}` for command `{}`",
|
||||
node.entry.primary
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Comprehensiveness gate (ADR-0053 D6): every runtime error class
|
||||
/// `friendly::error_hint_class` can return resolves to a tier-3
|
||||
/// `hint.err.<class>` block. Keep this list in sync with
|
||||
/// `error_hint_class` (its own unit tests pin the outputs).
|
||||
/// Diagnostic classes are deferred (issue #38), so not checked here.
|
||||
#[test]
|
||||
fn every_runtime_error_class_has_a_tier3_block() {
|
||||
let cat = crate::friendly::catalog();
|
||||
let classes = [
|
||||
"unique",
|
||||
"foreign_key.child_side",
|
||||
"foreign_key.parent_side",
|
||||
"not_null",
|
||||
"check",
|
||||
"type_mismatch",
|
||||
"not_found",
|
||||
"already_exists",
|
||||
"generic",
|
||||
"invalid_value",
|
||||
];
|
||||
for c in classes {
|
||||
let key = format!("hint.err.{c}.what");
|
||||
assert!(cat.get(&key).is_some(), "missing tier-3 error block `{key}`");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -647,6 +647,7 @@ pub const KEYS_AND_PLACEHOLDERS: &[(&str, &[&str])] = &[
|
||||
("shortcut.confirm", &[]),
|
||||
("shortcut.cycle", &[]),
|
||||
("shortcut.del_word", &[]),
|
||||
("shortcut.hint", &[]),
|
||||
("shortcut.history", &[]),
|
||||
("shortcut.home_end", &[]),
|
||||
("shortcut.load", &[]),
|
||||
|
||||
@@ -1165,6 +1165,7 @@ shortcut:
|
||||
browse: "browse"
|
||||
clear: "clear"
|
||||
complete: "complete"
|
||||
hint: "hint"
|
||||
history: "history"
|
||||
home_end: "home/end"
|
||||
del_word: "del word"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
source: src/ui.rs
|
||||
assertion_line: 2836
|
||||
assertion_line: 2839
|
||||
expression: snapshot
|
||||
---
|
||||
╭ Output ──────────────────────────────────────────────────────────────────────╮
|
||||
@@ -26,4 +26,4 @@ expression: snapshot
|
||||
│ │
|
||||
╰──────────────────────────────────────────────────────────────────────────────╯
|
||||
Project: Term Planner
|
||||
Ctrl-O sidebar · Tab complete · ↑ history · Enter run
|
||||
Ctrl-O sidebar · Tab complete · ↑ history · F1 hint · Enter run
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
source: src/ui.rs
|
||||
assertion_line: 2819
|
||||
assertion_line: 2822
|
||||
expression: snapshot
|
||||
---
|
||||
╭ Output ──────────────────────────────────────────────────────────────────────╮
|
||||
@@ -26,4 +26,4 @@ expression: snapshot
|
||||
│for SQL │
|
||||
╰──────────────────────────────────────────────────────────────────────────────╯
|
||||
Project: Term Planner
|
||||
Ctrl-O sidebar · Tab complete · ↑ history · Enter run
|
||||
Ctrl-O sidebar · Tab complete · ↑ history · F1 hint · Enter run
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
source: src/ui.rs
|
||||
assertion_line: 2827
|
||||
assertion_line: 2830
|
||||
expression: snapshot
|
||||
---
|
||||
╭ Output ──────────────────────────────────────────────────────────────────────╮
|
||||
@@ -26,4 +26,4 @@ expression: snapshot
|
||||
│for SQL │
|
||||
╰──────────────────────────────────────────────────────────────────────────────╯
|
||||
Project: Term Planner
|
||||
Ctrl-O sidebar · Tab complete · ↑ history · Enter run
|
||||
Ctrl-O sidebar · Tab complete · ↑ history · F1 hint · Enter run
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
---
|
||||
source: src/ui.rs
|
||||
assertion_line: 3442
|
||||
assertion_line: 3445
|
||||
expression: snapshot
|
||||
---
|
||||
╭ Output ────────────────────────────────────────────────────────────────────────────────╮
|
||||
@@ -28,4 +28,4 @@ expression: snapshot
|
||||
│ │
|
||||
╰────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
Project: Term Planner
|
||||
Ctrl-O sidebar · Tab complete · ↑ history · Enter run
|
||||
Ctrl-O sidebar · Tab complete · ↑ history · F1 hint · Enter run
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
source: src/ui.rs
|
||||
assertion_line: 3388
|
||||
assertion_line: 3391
|
||||
expression: snapshot
|
||||
---
|
||||
╭ Output ────────────────────────────────────────────────────────────────────────────────╮
|
||||
@@ -28,4 +28,4 @@ expression: snapshot
|
||||
│ │
|
||||
╰────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
Project: Term Planner
|
||||
Ctrl-O sidebar · Tab complete · ↑ history · Enter run
|
||||
Ctrl-O sidebar · Tab complete · ↑ history · F1 hint · Enter run
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
source: src/ui.rs
|
||||
assertion_line: 3378
|
||||
assertion_line: 3381
|
||||
expression: snapshot
|
||||
---
|
||||
╭ Output ────────────────────────────────────────────────────────────────────────────────╮
|
||||
@@ -28,4 +28,4 @@ expression: snapshot
|
||||
│ │
|
||||
╰────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
Project: Term Planner
|
||||
Ctrl-O sidebar · Tab complete · ↑ history · Enter run
|
||||
Ctrl-O sidebar · Tab complete · ↑ history · F1 hint · Enter run
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
source: src/ui.rs
|
||||
assertion_line: 3431
|
||||
assertion_line: 3434
|
||||
expression: snapshot
|
||||
---
|
||||
╭ Output ────────────────────────────────────────────────────────────────────────────────╮
|
||||
@@ -28,4 +28,4 @@ expression: snapshot
|
||||
│ │
|
||||
╰────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
Project: Term Planner
|
||||
Ctrl-O sidebar · Tab complete · ↑ history · Enter run
|
||||
Ctrl-O sidebar · Tab complete · ↑ history · F1 hint · Enter run
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
source: src/ui.rs
|
||||
assertion_line: 3457
|
||||
assertion_line: 3460
|
||||
expression: snapshot
|
||||
---
|
||||
╭ Output ────────────────────────────────────────────────────────────────────────────────╮
|
||||
@@ -28,4 +28,4 @@ expression: snapshot
|
||||
│ │
|
||||
╰────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
Project: Term Planner
|
||||
Ctrl-O sidebar · Tab complete · ↑ history · Enter run
|
||||
Ctrl-O sidebar · Tab complete · ↑ history · F1 hint · Enter run
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
---
|
||||
source: src/ui.rs
|
||||
assertion_line: 2880
|
||||
assertion_line: 2882
|
||||
expression: snapshot
|
||||
---
|
||||
╭ Output ──────────────────────────────────────────────────────────────────────╮
|
||||
@@ -26,4 +26,4 @@ expression: snapshot
|
||||
│insert into <Table> [(<col>[, ...])] [values] (<value>[, ...]) │
|
||||
╰──────────────────────────────────────────────────────────────────────────────╯
|
||||
Project: Term Planner
|
||||
Esc clear · Ctrl-A/E home/end · Ctrl-W del word · Enter run
|
||||
F1 hint · Esc clear · Ctrl-A/E home/end · Ctrl-W del word · Enter run
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
source: src/ui.rs
|
||||
assertion_line: 2896
|
||||
assertion_line: 2898
|
||||
expression: snapshot
|
||||
---
|
||||
╭ Output ──────────────────────────────────────────────────────────────────────╮
|
||||
@@ -26,4 +26,4 @@ expression: snapshot
|
||||
│ │
|
||||
╰──────────────────────────────────────────────────────────────────────────────╯
|
||||
Project: Term Planner
|
||||
Esc clear · Ctrl-A/E home/end · Ctrl-W del word · Enter run
|
||||
F1 hint · Esc clear · Ctrl-A/E home/end · Ctrl-W del word · Enter run
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
source: src/ui.rs
|
||||
assertion_line: 3099
|
||||
assertion_line: 3102
|
||||
expression: snapshot
|
||||
---
|
||||
╭ Tables ──────────────────╮╭ Output ────────────────────────────────────────────────────────────────────────╮
|
||||
@@ -26,4 +26,4 @@ expression: snapshot
|
||||
│ ││for SQL │
|
||||
╰──────────────────────────╯╰────────────────────────────────────────────────────────────────────────────────╯
|
||||
Project: Term Planner
|
||||
Ctrl-O sidebar · Tab complete · ↑ history · Enter run
|
||||
Ctrl-O sidebar · Tab complete · ↑ history · F1 hint · Enter run
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
source: src/ui.rs
|
||||
assertion_line: 2909
|
||||
assertion_line: 2912
|
||||
expression: snapshot
|
||||
---
|
||||
╭ Output ──────────────────────────────────────────────────────────────────────╮
|
||||
@@ -26,4 +26,4 @@ expression: snapshot
|
||||
│for SQL │
|
||||
╰──────────────────────────────────────────────────────────────────────────────╯
|
||||
Project: Term Planner
|
||||
Ctrl-O sidebar · Tab complete · ↑ history · Enter run
|
||||
Ctrl-O sidebar · Tab complete · ↑ history · F1 hint · Enter run
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
source: src/ui.rs
|
||||
assertion_line: 3209
|
||||
assertion_line: 3212
|
||||
expression: snapshot
|
||||
---
|
||||
╭ Tables ──────────────────╮╭ Output ────────────────────────────────────────────────────────────────────────╮
|
||||
@@ -26,4 +26,4 @@ expression: snapshot
|
||||
│ Orders.customer_id ││for SQL │
|
||||
╰──────────────────────────╯╰────────────────────────────────────────────────────────────────────────────────╯
|
||||
Project: Term Planner
|
||||
Ctrl-O sidebar · Tab complete · ↑ history · Enter run
|
||||
Ctrl-O sidebar · Tab complete · ↑ history · F1 hint · Enter run
|
||||
|
||||
@@ -46,4 +46,4 @@ expression: snapshot
|
||||
│with `mode advanced`, or prefix the line with `:` to run… │
|
||||
╰──────────────────────────────────────────────────────────╯
|
||||
Project: Term Planner
|
||||
Esc clear · Ctrl-A/E home/end · Ctrl-W del word · Ente
|
||||
F1 hint · Esc clear · Ctrl-A/E home/end · Ctrl-W del w
|
||||
|
||||
@@ -1894,22 +1894,25 @@ fn status_bar_bindings(app: &App) -> Vec<(&'static str, String)> {
|
||||
("Enter", crate::t!("shortcut.run")),
|
||||
];
|
||||
}
|
||||
// 4. Editing — the input has text: surface the readline edit keys
|
||||
// (ADR-0049). The highest-value subset stays within the width
|
||||
// budget; Ctrl-K/U remain unadvertised muscle memory.
|
||||
// 4. Editing — the input has text: F1 (the contextual hint for what
|
||||
// you're typing, ADR-0053) leads, then the readline edit keys
|
||||
// (ADR-0049). Ctrl-K/U remain unadvertised muscle memory.
|
||||
if !app.input.is_empty() {
|
||||
return vec![
|
||||
("F1", crate::t!("shortcut.hint")),
|
||||
("Esc", crate::t!("shortcut.clear")),
|
||||
("Ctrl-A/E", crate::t!("shortcut.home_end")),
|
||||
("Ctrl-W", crate::t!("shortcut.del_word")),
|
||||
("Enter", crate::t!("shortcut.run")),
|
||||
];
|
||||
}
|
||||
// 5. Default — empty input, Input focus.
|
||||
// 5. Default — empty input, Input focus. F1 here expands on the most
|
||||
// recent error, or points the user at getting started (ADR-0053).
|
||||
vec![
|
||||
("Ctrl-O", crate::t!("shortcut.nav")),
|
||||
("Tab", crate::t!("shortcut.complete")),
|
||||
("↑", crate::t!("shortcut.history")),
|
||||
("F1", crate::t!("shortcut.hint")),
|
||||
("Enter", crate::t!("shortcut.run")),
|
||||
]
|
||||
}
|
||||
@@ -2664,7 +2667,7 @@ mod tests {
|
||||
#[test]
|
||||
fn strip_default_state_is_nav_complete_history_run() {
|
||||
let app = App::new();
|
||||
assert_eq!(strip_keys(&app), vec!["Ctrl-O", "Tab", "↑", "Enter"]);
|
||||
assert_eq!(strip_keys(&app), vec!["Ctrl-O", "Tab", "↑", "F1", "Enter"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -2675,7 +2678,7 @@ mod tests {
|
||||
app.input.push_str("create ta");
|
||||
assert_eq!(
|
||||
strip_keys(&app),
|
||||
vec!["Esc", "Ctrl-A/E", "Ctrl-W", "Enter"],
|
||||
vec!["F1", "Esc", "Ctrl-A/E", "Ctrl-W", "Enter"],
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user