Files
rdbms-playground/docs/requirements.md
T
claude@clouddev1 165068269b Foreign-key relationships, rebuild-table, polish round
DSL:
- add 1:n relationship [as <name>] from <P>.<col> to <C>.<col>
  [on delete <action>] [on update <action>] [--create-fk]
- drop relationship <name> | from <P>.<col> to <C>.<col>
- show table <name> for re-displaying a structure on demand

Database (ADR-0013):
- Rebuild-table primitive following SQLite's
  ALTER-via-rebuild recipe (foreign_keys=OFF outside tx,
  copy-by-name, foreign_key_check before commit). Reusable for
  B2 (column drops/renames/type changes).
- ReferentialAction enum (no action / restrict / set null /
  cascade); SET DEFAULT awaits column DEFAULTs.
- __rdbms_playground_relationships metadata table -- names,
  auto-generated as <Parent>_<pcol>_to_<Child>_<ccol>.
- Type::fk_target_type() validation at declaration; friendly
  errors for type mismatch, non-PK target, missing column,
  duplicate name.
- describe_table populates symmetric outbound + inbound
  relationship lists. drop_table refuses while inbound
  references exist; outbound metadata cleaned up alongside drop.

App / UI:
- In-line cursor editing in the input field: Left, Right,
  Home, End, Delete, Backspace honoring UTF-8 boundaries.
- PageUp / PageDown scrolls the output buffer; viewport row
  count fed back from the renderer via App::note_output_viewport
  so scroll is capped against the actual visible area
  (regression-tested) and snaps to the bottom on new output.
- Failure messages quote the command portion ("verb target"
  failed: ...) for visual clarity; RelationshipSelector has a
  proper Display impl so "no such relationship" reads cleanly.
- Structure rendering shows References / Referenced by sections.

Docs:
- ADR-0013 covers naming, metadata table, symmetric view, and
  the rebuild-table strategy.
- requirements.md updates: C3 (FK done), B2 (primitive in),
  T3 (compound-PK FK still pending). New entries: I1a (cursor
  editing -- landed), I1b (Ctrl-A/E and readline shortcuts --
  pending), V4 partial scroll, V5 (show family), C3a (modify
  relationship -- deferred).

Tests: 154 passing (140 lib + 14 integration), 0 skipped.
Clippy clean with nursery enabled.
2026-05-07 14:52:51 +00:00

399 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# RDBMS Playground — Requirements (Phase 1)
This document is the **consolidated Phase 1 requirements
checklist** for RDBMS Playground. It captures everything the
project has committed to so far, derived from the design
conversation and the ADRs in `docs/adr/`.
**Purpose.** Phase 5 verification at every milestone measures
delivered work against this checklist. An item not on this list
was not promised; an item silently dropped without confirmation
is a process failure.
**Scope.** The list is intentionally coarse — each item is a
unit of "satisfied / not satisfied" judgement. When an item is
taken up for implementation, it is decomposed further in a
backlog (initially in this repo, later in GitHub issues once the
repo is pushed).
## Status legend
- `[ ]` — open, not yet implemented
- `[x]` — satisfied (implemented + tested)
- `[~]` — deferred, awaiting an ADR or further design before any
implementation
- `[-]` — explicitly out of scope (rationale at the bottom)
## Test baseline
No test suite exists yet — the repo currently contains only
docs. The baseline is therefore "0 passing, 0 failing, 0
skipped." Subsequent phases establish the suite and measure
against it.
---
## Distribution and install
- [ ] **D1** Cross-platform binaries: Linux, macOS, Windows on
x86_64 and aarch64.
- [ ] **D2** Single static binary, no runtime dependencies.
- [ ] **D3** Released via prebuilt binaries plus Homebrew, Scoop,
`winget`, and `cargo binstall`.
## TUI shell
- [ ] **S1** Three-region layout: items list (left), output
panel (right), input field (bottom).
- [ ] **S2** Items list shows tables and per-table indexes;
designed to extend to additional element kinds (relations,
views, etc.) without restructuring.
*(Progress: tables are listed live from the database; indexes
pending alongside C3 index support.)*
- [ ] **S3** Output panel renders a visualization of the
currently selected item and supports multiple tabs.
- [ ] **S4** Hint area below the input field; keyboard-toggleable
for inspecting hints about the current input or last error.
- [ ] **S5** Mode label and distinct border style on the input
field communicate the current input mode at all times.
## Input field
- [ ] **I1** Multi-line entry that auto-expands; Ctrl-Enter (or
equivalent) submits, plain Enter inserts a newline.
- [ ] **I1a** In-line cursor editing in the input field: Left /
Right arrows move the cursor by character (UTF-8 boundaries
honoured), Home / End jump to the extremes, Delete removes the
character at the cursor, Backspace removes the character
before. Insertion happens at the cursor position. *(Implemented;
multi-line editing per I1 still pending.)*
- [ ] **I1b** Readline-style cursor shortcuts: Ctrl-A / Ctrl-E
as aliases for Home / End for users on keyboards without those
keys (and for ergonomics in command-driven workflows). Likely
followed by Ctrl-W (delete previous word), Ctrl-K (delete to
end), Ctrl-U (delete to start). Pending.
- [ ] **I2** Persistent navigable input history (project-scoped,
with a global rolling history also available).
*(Progress: in-memory navigable history (Up/Down arrows, draft
preservation, dedup of consecutive duplicates) is implemented;
persistence across sessions arrives with track 2's project
storage.)*
- [ ] **I3** Tab completion for app commands, DSL keywords, table
names, column names, and SQL keywords.
- [ ] **I4** Syntax highlighting for both the DSL and SQL.
- [ ] **I5** In-flight query/command cancellation (Ctrl-C in the
output area or input field).
## Input modes (per ADR-0003)
- [ ] **M1** Simple mode is the default. It accepts DSL data
commands and the canonical app-level commands; raw SQL is
rejected with a friendly hint.
- [ ] **M2** Advanced mode accepts SQL plus the canonical
app-level commands without any sigil.
- [ ] **M3** Prefixing a single line with `:` in simple mode is a
one-shot advanced escape (with the prompt label updated). The
`mode simple` / `mode advanced` command switches modes
persistently.
## App-level commands (per ADR-0003)
- [ ] **A1** All canonical app-level commands implemented and
available in both modes: `save`, `save as`, `load`, `new`,
`export`, `import`, `seed`, `replay`, `undo`, `redo`, `mode`,
`help`, `hint`, `quit`.
*(Progress: `quit`/`q` and `mode simple|advanced` implemented;
the rest land alongside the features they belong to — `save`
and friends in track 2, `seed` in the seeding iteration, etc.)*
## DSL data commands
- [ ] **C1** Table operations: create / drop / rename.
*(Progress: create + drop done; rename pending.)*
- [ ] **C2** Column operations: add / drop / rename / change
type, including the rebuild-table dance behind the scenes
where SQLite ALTER cannot do it directly.
*(Progress: add done; drop/rename/change-type pending — the
rebuild-table dance is the gating piece, B2.)*
- [ ] **C3** Schema constraints: primary key (single and
compound), foreign key with `ON DELETE` / `ON UPDATE` referential
actions, indexes, `NOT NULL`, `UNIQUE`, `CHECK`, `DEFAULT`.
*(Progress: PK including compound done at create-table time;
FK with `ON DELETE` / `ON UPDATE` actions done (ADR-0013) —
declared via `add 1:n relationship`; symmetric outbound +
inbound view in the structure renderer; type compatibility
validated at declaration via `Type::fk_target_type()`. Index,
`NOT NULL`, `UNIQUE`, `CHECK`, `DEFAULT` still pending.)*
- [~] **C3a** Modify relationship: `modify relationship <name>
[on delete <action>] [on update <action>]`. Users can achieve
the same via drop + add today; one-step modify is a small
follow-up using the existing rebuild-table machinery. ADR
pending.
- [ ] **C4** Convenience: `create m:n relationship from <T1> to
<T2>` produces an auto-named junction table the user can rename;
pulls primary keys and FK definitions automatically.
- [ ] **C5** Data operations: insert / update / delete via DSL.
## SQL handling
- [ ] **Q1** SQL parsed via `sqlparser-rs`; supported subset is
defined (specifics deferred to a future ADR).
*(Progress: DSL is parsed via `chumsky` (ADR-0009); SQL
handling in advanced mode is still a placeholder echo.)*
- [ ] **Q2** Non-standard syntax rejected with a clear message
pointing at the supported subset.
- [x] **Q3** User-facing simplified types map transparently to
SQLite STRICT types in generated DDL. *(All ten types implemented
and tested.)*
- [~] **Q4** Supported SQL subset specification — design and ADR
pending. Q1 cannot be marked satisfied without it.
## Database backend (per ADR-0002)
- [x] **B1** SQLite via `rusqlite`; all tables created `STRICT`;
`PRAGMA foreign_keys = ON` per connection. *(Database accessed
through a dedicated worker thread per ADR-0010.)*
- [ ] **B2** Schema evolution uses the rebuild-table technique
internally where SQLite `ALTER TABLE` cannot.
*(Progress: rebuild-table primitive landed (ADR-0013) and is
used by `add_relationship` / `drop_relationship`. Reuse for
column drops/renames/type changes pending; the primitive is
designed to support those without further architectural work.)*
- [ ] **B3** Query timeout and cancellation supported (no
cartesian-join-of-doom can hang the app).
*(Progress: the worker-thread architecture is in place; the
cancellation/timeout protocol on top of it is pending.)*
## Type system (per ADR-0005)
- [x] **T1** All ten user-facing types implemented: `text`,
`int`, `real`, `decimal`, `bool`, `date`, `datetime`, `blob`,
`serial`, `shortid`. *(Mapping to SQLite STRICT covered by
ADR-0005; FK target type rule by ADR-0011.)*
- [ ] **T2** `shortid` generation: base58, 1012 characters,
omits ambiguous characters; generated client-side at insert.
*(Type exists; insert-time generation arrives with the data
insertion path.)*
- [ ] **T3** Compound primary keys handled end-to-end (DSL,
storage, display, FK reference).
*(Progress: DSL grammar (`with pk a:int,b:int`), storage, and
table-info description are all present; the FK iteration
references single-column PKs only — compound-key FK references
remain pending.)*
## Visualizations
- [ ] **V1** Single-element views render in the output pane: a
selected table as its structure (columns, types, keys,
constraints); a selected relationship as two tables joined by
a line.
*(Progress: a basic structure view (column rows with SQLite
type names) is rendered after each successful DDL; pretty
rendering, selection nav, and relationship line-art pending —
see V4 for the broader direction.)*
- [ ] **V2** SQL query results render as a dynamic table view in
the output pane, with multiple result tabs supported.
- [~] **V3** Full ER-diagram export (whole-database graph, viewed
outside the TUI) — low priority; design and ADR pending.
- [~] **V4** Output panel as a *scrollable per-session log* with
inline rich rendering. Direction agreed in conversation: the
output area is a chronological journal of operations and
selections (e.g. a "selected table X" entry with the rendered
structure underneath); structure renderings choose between a
compact ASCII-table form and a vertical line-per-column form
based on dimensions; the log is exportable to Markdown so
learners can keep a record of their session. Design and ADR
pending before any implementation.
*(Partial: PageUp / PageDown scrolling of the existing line
buffer is in, with new output snapping the view to the most
recent. The full V4 scope — smart structure rendering, log
styling, Markdown export, scroll indicator — remains pending.)*
- [ ] **V5** `show <kind> [<name>]` family of commands for
redisplaying schema info on demand. *(Progress: `show table
<name>` implemented and reuses the structure-render pipeline;
`show tables`, `show relationships`, etc. pending.)*
## Project lifecycle (per ADR-0004)
- [ ] **P1** An auto-named temporary project is created on
startup unless a project is specified, and stored in a
platform-standard path
(e.g. `~/.rdbms-playground/projects/temp-<name>`).
- [ ] **P2** `save` elevates a temp project to a named project at
a chosen location.
- [ ] **P3** Project is always saved as changes occur — there is
no manual dirty state.
- [ ] **P4** `load` opens a picker listing temp projects with
timestamps, with the option to browse to an arbitrary location.
- [ ] **P5** `playground.db` is a derived artifact: rebuilt
silently when missing, rebuilt with confirmation and a change
summary when present (per ADR-0004).
## Project file format (per ADR-0004)
- [ ] **F1** `project.yaml` with `version` field carries schema,
relationships, and project metadata; `data/<table>.csv` carries
table data (UTF-8, header row, RFC 4180).
- [ ] **F2** A `.gitignore` template (excluding `playground.db`)
is created in each new project.
- [ ] **F3** Project file format includes a registered-migrator
mechanism so older `version` values load cleanly as the format
evolves. (Exercised once `version` increments past 1; the
mechanism itself is built in v1.)
## Undo and replay (per ADR-0006)
- [ ] **U1** Auto-snapshot before destructive operations into a
ring buffer (initial size N=10, tunable).
- [ ] **U2** `undo` restores the most recent snapshot; `redo`
re-applies; both prompt for confirmation showing the snapshot
timestamp and a summary of the changes that will be discarded.
- [ ] **U3** `history.log` records every successfully executed
command in append-only form.
- [ ] **U4** `replay` runs commands from a `history.log` or
`.commands` file.
## Sharing and export (per ADR-0007)
- [ ] **E1** `export` produces a zip excluding `playground.db`;
default filename `YYYYMMDD-<projectname>-export-NN.zip` with a
non-clobbering two-digit sequence.
- [ ] **E2** User documentation includes sharing recipes for
git, email, and direct file transfer.
## Sample data / seeding
- [ ] **SD1** `seed <table> [count]` generates plausible fake
data; junction tables are seeded with valid foreign-key
references drawn from existing parent rows.
- [~] **SD2** Detailed seeding rules (per-type generators,
locale, determinism, override hooks) — design and ADR pending.
## Query analysis
- [ ] **QA1** `EXPLAIN QUERY PLAN` is run on demand for queries;
output is rendered as an annotated tree highlighting full
scans, index use, and join order.
- [~] **QA2** Plan rendering specifics (tree layout, annotation
taxonomy, colour scheme) — design and ADR pending.
## Hints, help, errors
- [ ] **H1** Friendly error-rewriting layer translates SQLite
error messages into learner-friendly equivalents.
- [ ] **H2** `hint` provides contextual help for the current
input or the most recent error.
- [ ] **H3** `help` provides general reference and per-command
help.
## CLI
- [ ] **L1** Load a project via a positional CLI argument.
- [~] **L2** Submit a command alongside project load — deferred,
not v1.
## Tutorials and lessons
- [~] **TU1** Tutorial / lesson system — design and ADR pending
before any implementation. Out of v1 unless an ADR is written.
## Testing (per ADR-0008)
- [ ] **TT1** Tier 1: `cargo test` + `proptest` covering
pure-logic modules (parser, dispatcher, type mapping, project
I/O, snapshot ring buffer, replay log).
- [ ] **TT2** Tier 2: Ratatui `TestBackend` + `insta` snapshots
for representative views.
- [ ] **TT3** Tier 3: synthetic event-loop integration tests
covering the user-facing flows in this checklist.
- [ ] **TT4** Tier 4: PTY-based end-to-end for the four critical
flows named in ADR-0008 (cold launch → DDL → quit; save →
reopen; export → import → rebuild; undo after DROP).
- [ ] **TT5** CI runs all tiers on Linux, macOS, and Windows on
stable Rust.
## Cross-cutting
- [ ] **X1** Comprehensive logging via the project's logging
infrastructure per `CLAUDE.md` (decision points, parameter
values, fallback paths).
- [~] **X2** Language: English-only for v1; multi-language is an
open question to revisit later.
- [~] **X3** Accessibility: TUI screen-reader support is
best-effort and not a v1 commitment; revisit if user need
emerges.
---
## Non-functional requirements
NFRs are quality bars rather than discrete features. Where a
target is measurable, it is stated numerically; where it is
necessarily qualitative, the criterion is named and the bar is
"reviewer judgement against the criterion."
- [ ] **NFR-1 Performance — startup.** Cold launch to first
rendered frame under 500ms on commodity hardware (developer
laptop, mid-range desktop). Measured in CI on the Linux runner
as a regression gate.
- [ ] **NFR-2 Performance — input latency.** Keystroke-to-render
latency under 16ms during normal editing; long-running queries
must execute off the UI thread so the interface remains
responsive (typing, scrolling, mode switching) while a query is
running.
- [ ] **NFR-3 Performance — resource footprint.** Idle memory
under 50MB on the smallest target platform; no busy-loops; CPU
near zero when waiting for input.
- [ ] **NFR-4 Visual quality — distinctive design.** Colour
palette and typography are deliberate and consistent across
views; layout uses Unicode box-drawing and symbols where they
add clarity; rendering avoids the generic flat-default look
that ships with most TUI frameworks. Criterion: a reviewer can
identify the app from a screenshot of any view.
- [ ] **NFR-5 Visual quality — colour use.** Colour conveys
information rather than decoration: mode indication, query
result types (numeric vs text vs null), error severity,
syntax highlighting categories. Foreground/background
combinations meet WCAG-AA contrast (4.5:1 for normal text)
even though we have not committed to broader accessibility.
- [ ] **NFR-6 Cross-platform parity.** Behaviour and visual
quality are equivalent across Linux, macOS, and Windows on
crossterm-supported terminals. Platform-specific divergence
(e.g. font fallbacks) is documented, not silently tolerated.
- [ ] **NFR-7 Light and dark background support.** The colour
scheme remains legible and visually coherent on both light and
dark terminal backgrounds. The mechanism (auto-detect via
terminal query, explicit user setting, or both) is an
implementation choice, but the outcome is non-negotiable: no
dark-on-dark or light-on-light readability failures on either
background.
---
## Explicitly out of scope
- [-] **N1** Hosted publishing platform — per ADR-0007. Sharing
is local-artifact based.
- [-] **N2** Real UUID column type — per ADR-0005. The `shortid`
type covers the pedagogical need at TUI-friendly width.
- [-] **N3** Cross-emulator visual regression coverage — per
ADR-0008. Crossterm abstracts terminals adequately; we revisit
only if a real regression surfaces.
---
## Maintenance
This document is updated whenever:
- A new requirement is committed to (added as a new item with the
next free ID in its section).
- A deferred item is taken up (status moves from `[~]` to `[ ]`).
- An item is satisfied (status moves to `[x]`, with a reference
to the commit, PR, or test that demonstrates it).
- An item moves out of scope (status moves to `[-]` with a
rationale and a link to the decision).
IDs are stable: once assigned, they are not reused. Removing a
requirement leaves a "withdrawn" entry referencing the decision.