Files
rdbms-playground/docs/handoff/20260615-handoff-71.md
T
claude@clouddev1 b4441507e2 docs: handoff 71 — hint content needs a semantic verification pass
User smoke-test found hint.cmd.create_table is semantically wrong: the
example `create table Customers with pk id(serial), name(text),
email(text)` reads as a 3-column table but actually declares a compound
PK (id, name, email) — everything after `with pk` is the PK column list
(ADR-0005). Root cause: Phase C examples were syntax-checked but some
were extrapolated, not verified to *do* what what/concept claims. Handoff
specifies a full per-block semantic pass (run each example / check the
ADR) + a ready-to-apply create_table fix.
2026-06-15 17:14:22 +00:00

5.7 KiB
Raw Blame History

Session handoff — 2026-06-15 (71)

Short, focused handover. Continues immediately from handoff-70 (which shipped H2 / the contextual hint, ADR-0053). A user smoke-test surfaced a correctness bug in the hint content, and it implicates the whole corpus. This handoff exists so the next session does a systematic semantic verification pass over every hint block — context ran too low to do it now.

§1. State

Branch: main, clean, all committed (local; push pending). 2499 pass / 1 ignored, clippy clean. Open issues: #35#38 (see handoff-70). H2 / ADR-0053 is functionally complete; the content is not trustworthy until the pass below is done.

§2. The bug (confirmed)

hint.cmd.create_table (in src/friendly/strings/en-US.yaml) reads:

What:    Create a new table — its columns, their types, and a primary key.
Example: create table Customers with pk id(serial), name(text), email(text)
Concept: A table is a set of rows that share the same columns. The primary
         key uniquely identifies each row; a `serial` key numbers the rows for you.

This is wrong. In the DSL, everything after with pk is the primary-key column list (a possibly compound PK, ADR-0005). So the example does not create a table with pk=id plus regular columns name/email — it creates a table whose compound primary key is (id, name, email). Non-key columns are added separately with add column. The what ("its columns, their types") and the example both mislead a learner badly.

  • Evidence: real test usage is create table Orders with pk id(serial), CustId(int) (a 2-column compound PK) and the common form create table X with pk id(int) (single-column PK only). The usage template create table <Name> with pk [<col>(<type>)[, ...]] is itself misleading — the [, ...] is the PK list, not regular columns.
  • Correct mental model: create table <T> with pk <pk-cols…> then add column <T>: <name> (<type>) for each non-key column. Confirm against ADR-0005 (compound PK) and ADR-0009 (DSL syntax) when fixing.

§3. Root cause — why this needs a full pass

During Phase C I verified some examples against parse.usage.* templates and real test greps, but for others I extrapolated beyond verified syntax. For create_table I saw ... with pk id(int) (single col) and wrongly generalised to "pk + more columns," misreading the with pk list as a column list. The examples are syntactically checked but not semantically — i.e. not verified to do what the what/concept claims.

So the corpus needs a pass that, for every hint.cmd.* and hint.err.* block, checks:

  1. the example parses and runs, and
  2. it actually demonstrates what what/concept says, and
  3. what/concept are factually true of the real behaviour.

Don't trust grep+extrapolation. Prefer: run the example in the app (or a Tier-3 test), or check it against the authoritative ADR.

§4. The pass — how to do it (next session)

The corpus lives in src/friendly/strings/en-US.yaml under hint.cmd.* (per command form) and hint.err.* (per runtime error class). The inventory and authoritative syntax sources:

  • hint.cmd.<form> — for each, cross-check the example against the matching parse.usage.<form> template and the form's ADR, and run it. Highest-risk (extrapolated, verify first): DDLcreate_table (known wrong), add_column, add_index, add_constraint, change_column, drop_*, create_m2n; advanced-SQL — confirm each is in the supported SQL subset (select, with CTE, sql_insert/update/delete, sql_create_table, sql_alter_table, sql_create_index/drop_index/drop_table, explain_sql); DMLseed forms, explain, show_*, update/delete (--all-rows / required-WHERE wording). App commands are lower-risk (reference-style).
  • hint.err.<class> — verify the fix recipe in example is actually the right remedy and concept matches the engine's real behaviour (FK sides, on delete actions, check/not_null/unique semantics).
  • Relevant ADRs: 0005 (types + compound PK), 0009 (DSL syntax), 0011 (FK type compat), 0013 (relationships/rebuild), 0014 (data ops + required-WHERE), 0025 (indexes), 0028/0039 (explain), 00300036 (SQL subset), 0048 (seed). docs/requirements.md for scope.

Suggested method: drive the app (/run or a small PTY/Tier-3 harness) and actually execute each example; or add a test that parses+runs every hint.cmd.* example and asserts success. The latter would also be a durable regression guard — consider adding it as part of the pass (it upgrades the comprehensiveness coverage test from "a block exists" to "the example actually works").

§5. Immediate fix ready to apply

create_table is diagnosed (§2). The corrected block should make the example a PK-only create table and move the regular columns to a follow-up add column, e.g.:

What:    Create a new table with its primary key.
Example: create table Customers with pk id(serial)
Concept: A table is a set of rows sharing the same columns. `with pk`
         declares the primary key (one column, or several for a compound
         key); add the other columns afterwards with `add column`.

Apply this (and re-check create_m2n / add_* while there), but only as part of the systematic pass — a one-off fix risks leaving siblings wrong.

§6. How to take over

  1. Read handoffs 70 → 71, CLAUDE.md.
  2. Confirm green: cargo test (2499 / 1 ignored), cargo clippy --all-targets.
  3. Do the §4 pass (consider the run-every-example test in §4). Test-first, /runda before commit, confirm the commit message with the user.
  4. Pedagogy wins — these are teaching strings; correctness and clarity over cleverness.