feat(hint): H2 Phase B — per-form keying + the three exemplars (ADR-0053)

The first exemplar (`add 1:n relationship`) showed per-node keying is
too coarse for multi-form commands, so revise the mechanism to per-form.

- CommandNode `hint_id: Option<&str>` -> `hint_ids: &[&str]` (mirrors
  usage_ids); hint_key_for_input_in_mode reuses a factored-out
  pick_form_key (shared digit/m:n/suffix form disambiguation with
  usage_key_for_input_in_mode)
- wire INSERT + ADD (all four forms) with hint_ids
- author the three approved exemplars: hint.cmd.insert,
  hint.cmd.add_relationship, hint.err.foreign_key.child_side
  (what/example/concept) + keys.rs registration
- revise ADR-0053 D3 to per-form; record clause-concept hints as a
  deferred extension (issue #37); update README + plan
- +5 tests; 2488 pass / 1 ignored, clippy clean
This commit is contained in:
claude@clouddev1
2026-06-15 12:18:41 +00:00
parent 050b36391e
commit 4a5fd1b5c1
11 changed files with 292 additions and 109 deletions
+14 -13
View File
@@ -1790,7 +1790,7 @@ pub static SHOW: CommandNode = CommandNode {
shape: SHOW_SHAPE,
ast_builder: build_show,
help_id: Some("data.show"),
hint_id: None,
hint_ids: &[],
usage_ids: &[
"parse.usage.show_data",
"parse.usage.show_table",
@@ -1806,7 +1806,7 @@ pub static SEED: CommandNode = CommandNode {
shape: SEED_SHAPE,
ast_builder: build_seed,
help_id: Some("data.seed"),
hint_id: None,
hint_ids: &[],
usage_ids: &["parse.usage.seed"],
};
@@ -1815,7 +1815,8 @@ pub static INSERT: CommandNode = CommandNode {
shape: INSERT_SHAPE,
ast_builder: build_insert,
help_id: Some("data.insert"),
hint_id: None,
// ADR-0053 Phase-B exemplar.
hint_ids: &["insert"],
usage_ids: &["parse.usage.insert"],};
pub static UPDATE: CommandNode = CommandNode {
@@ -1823,7 +1824,7 @@ pub static UPDATE: CommandNode = CommandNode {
shape: UPDATE_SHAPE,
ast_builder: build_update,
help_id: Some("data.update"),
hint_id: None,
hint_ids: &[],
usage_ids: &["parse.usage.update"],};
pub static DELETE: CommandNode = CommandNode {
@@ -1831,7 +1832,7 @@ pub static DELETE: CommandNode = CommandNode {
shape: DELETE_SHAPE,
ast_builder: build_delete,
help_id: Some("data.delete"),
hint_id: None,
hint_ids: &[],
usage_ids: &["parse.usage.delete"],};
pub static REPLAY: CommandNode = CommandNode {
@@ -1839,7 +1840,7 @@ pub static REPLAY: CommandNode = CommandNode {
shape: REPLAY_PATH,
ast_builder: build_replay,
help_id: Some("data.replay"),
hint_id: None,
hint_ids: &[],
usage_ids: &["parse.usage.replay"],};
pub static EXPLAIN: CommandNode = CommandNode {
@@ -1847,7 +1848,7 @@ pub static EXPLAIN: CommandNode = CommandNode {
shape: EXPLAIN_SHAPE,
ast_builder: build_explain,
help_id: Some("data.explain"),
hint_id: None,
hint_ids: &[],
usage_ids: &["parse.usage.explain"],};
/// `explain` over advanced-mode SQL (ADR-0039).
@@ -1867,7 +1868,7 @@ pub static EXPLAIN_SQL: CommandNode = CommandNode {
// too). Mirrors the `SQL_INSERT`/`SQL_UPDATE`/`SQL_DELETE`
// precedent; otherwise `note_help` would print `explain` twice.
help_id: None,
hint_id: None,
hint_ids: &[],
usage_ids: &[],};
/// SQL `SELECT` (ADR-0030 §6, ADR-0031, ADR-0032).
@@ -1883,7 +1884,7 @@ pub static SELECT: CommandNode = CommandNode {
shape: Node::Subgrammar(&sql_select::SQL_SELECT_TAIL),
ast_builder: build_select,
help_id: None,
hint_id: None,
hint_ids: &[],
usage_ids: &["parse.usage.select"],};
/// `WITH …` top-level statement (ADR-0032 §4 / sub-phase 2c).
@@ -1898,7 +1899,7 @@ pub static WITH: CommandNode = CommandNode {
shape: Node::Subgrammar(&sql_select::SQL_WITH_TAIL),
ast_builder: build_select,
help_id: None,
hint_id: None,
hint_ids: &[],
usage_ids: &["parse.usage.with"],};
/// SQL `INSERT` — the `Advanced`-category node of the shared
@@ -1916,7 +1917,7 @@ pub static SQL_INSERT: CommandNode = CommandNode {
shape: Node::Subgrammar(&sql_insert::SQL_INSERT_SHAPE),
ast_builder: build_sql_insert,
help_id: None,
hint_id: None,
hint_ids: &[],
usage_ids: &[],
};
@@ -1930,7 +1931,7 @@ pub static SQL_UPDATE: CommandNode = CommandNode {
shape: Node::Subgrammar(&sql_update::SQL_UPDATE_SHAPE),
ast_builder: build_sql_update,
help_id: None,
hint_id: None,
hint_ids: &[],
usage_ids: &[],
};
@@ -1946,7 +1947,7 @@ pub static SQL_DELETE: CommandNode = CommandNode {
shape: Node::Subgrammar(&sql_delete::SQL_DELETE_SHAPE),
ast_builder: build_sql_delete,
help_id: None,
hint_id: None,
hint_ids: &[],
usage_ids: &[],
};