docs: move website ADR + plan into a dedicated docs/website/ namespace

The website subproject drew ADR numbers from the same global integer pool
as main, so every merge risked a collision — this already happened twice
(drafted 0042, bumped to 0044, both landing on numbers main had taken; main
has now used 0044 for relationship visualization). Give the website its own
ADR namespace so the two never compete again.

- docs/adr/0044-public-website-...md
    -> docs/website/adr/20260604-adr-website-001.md  (id: ADR-website-001)
- docs/plans/20260604-adr-0044-website.md
    -> docs/website/plans/20260604-website-implementation-plan.md
- new docs/website/adr/README.md index (dated <date>-adr-website-<NNN> seq)
- docs/adr/README.md: drop the 0044 entry, add a namespace pointer in the
  intro (keeps the list tail == merge-base, so main's 0044 merges cleanly)
- ADR-0000: record the subproject-ADR-namespace convention
- update references in STYLE.md, astro.config.mjs, the plan body

Handoff files left untouched as point-in-time history.
This commit is contained in:
claude@clouddev1
2026-06-10 11:04:55 +00:00
parent 39e97ac3f9
commit dfb5f0b1b1
7 changed files with 62 additions and 15 deletions
@@ -58,6 +58,24 @@ compute "next" from a feature branch. A branch that genuinely needs a real
number up front may instead reserve one by landing a stub index entry on
`main` first, but placeholder-until-merge is the default.
### Subproject ADR namespaces
A long-lived subproject developed on its own branch can escape the shared
integer pool entirely by keeping its decision records in a **separate
namespace**, rather than fighting collisions on every merge. The **website**
(`docs/website/adr/`) is the first: its ADRs use a dated sequence —
`<date>-adr-website-<NNN>.md`, referenced in prose as `ADR-website-NNN`
and are indexed by their own `docs/website/adr/README.md`. Because the
date-plus-subproject prefix is disjoint from `main`'s integer sequence, a
website ADR and a `main` ADR can never claim "the same number" again. (This
namespace was created on 2026-06-10 after the website's ADR collided with
`main`'s on consecutive numbers — drafted 0042, bumped to 0044, both times
landing on a number `main` had taken; the move retired it from the pool as
**ADR-website-001**.) The main `docs/adr/` index carries a pointer to each
such namespace. Use this for a new subproject only when it is genuinely
self-contained and branch-isolated; one-off cross-cutting decisions stay in
the global sequence.
## Out-of-scope discipline
ADRs (and the plans they spawn) lean heavily on "out of scope" language.
@@ -1,129 +0,0 @@
# ADR-0044: Public website and documentation site
## Status
Accepted (2026-06-04). Implementation plan:
[`docs/plans/20260604-adr-0044-website.md`](../plans/20260604-adr-0044-website.md).
> Renumbered from ADR-0042 to ADR-0044 when the `website` branch merged
> `main` (2026-06-09): `main` had independently used 0042 for the H1a
> parse-error ADR and 0043 for compound-PK FK references. Content is
> unchanged from the original draft.
## Context
RDBMS Playground is nearing its first public release and needs a public
website that does two jobs: **attract** — a landing page that shows the
playground in action — and **document** — a thorough, canonical reference
for everything the playground can do.
The documentation-heavy surface is already implemented and verified (full
simple- and advanced-mode command set, the ten-type vocabulary,
relationships, constraints, indexes, EXPLAIN, undo/history/replay, projects,
export/import, the teaching echo, clipboard, friendly errors, tab completion
and syntax highlighting; 2151 tests passing at the time of writing). The
site is therefore largely a presentation-and-writing effort, not a
wait-for-features one. A grounded inventory of what is shippable now lives
in the implementation plan.
Several choices here had no canonical default; they were settled during a
planning + `/runda` pass with the user and are recorded below.
## Decision
1. **Stack — Astro 6 + Starlight + Tailwind v4.** Astro's content-first,
zero-JS-by-default model with the Starlight docs theme fits a
marketing-landing-plus-heavy-docs site better than the alternative
considered, SvelteKit + Tailwind (the usual go-to here). Interactive
pieces are added as Astro islands (Svelte or vanilla), so Svelte is still
available where it earns its place. Tailwind v4 is wired via the official
`@tailwindcss/vite` plugin; the `@astrojs/starlight-tailwind` plugin
bridges Tailwind with Starlight's theming.
2. **Demo medium — asciinema.** Showcase sequences are recorded as
asciinema `.cast` files (text-based, small, faithful to the full
alternate-screen render) and embedded with `asciinema-player`. The same
casts are reused inline in the docs — one recording format serves both
the landing page and documentation enrichment. Recordings are produced by
a **scripted-input driver** that types commands into a real PTY with
viewer-friendly pacing; the app's own `history.log` **replay** (ADR-0034)
re-executes commands without typing animation or pacing and is therefore
suitable only for state-deterministic docs snippets, not the hero demo.
3. **In-page WASM playground — deferred** (OOS: **deferred**, not rejected).
A live, type-it-yourself playground compiled from the Rust app to
WebAssembly is desirable but is a multi-week sub-project, so it does not
block the site. The demo section is designed with a stable seam (a single
`Demo` component contract) so a WASM playground island can replace the
asciinema player later with no change to call sites. Recorded boundary
for that future work:
- **Portable core (runs on `wasm32-unknown-unknown` largely as-is):**
`src/dsl/*` (parser, types, grammar, walker), the pure `App::update()`,
`ui.rs`, `theme.rs`, `friendly/*`, output rendering; an in-memory DB
path already exists (`Connection::open_in_memory()`). `rusqlite`
compiles to the browser target via its `ffi-sqlite-wasm-rs` feature.
- **Native edge needing `cfg`-gated browser replacements:** the
multi-thread Tokio runtime + the dedicated DB **worker thread**
(ADR-0010) → current-thread/in-line async; `crossterm` terminal +
event-stream → a browser backend (e.g. Ratzilla's DOM/Canvas) + DOM
events; `arboard`, `zip`, file persistence (ADR-0015), file logging;
and the rusqlite **backup-API** undo (ADR-0006) → a SQL dump/restore.
When taken up, this becomes its own ADR + iteration plan.
4. **Hosting — portable static build; Vercel is the likely target.** Astro 6
builds to static HTML/CSS with no adapter, so the output deploys equally
to Vercel, Cloudflare Pages, Netlify, or GitHub Pages. We avoid coupling
to any one host. **No CI yet** — the site is tested locally (`pnpm dev` /
`pnpm build`) until the repo reaches its public home.
5. **Repo topology — monorepo.** The site lives under `website/` in the
playground repo; the crate stays at the repo root. The repo as a whole
moves to its public home later; site and crate travel together.
6. **Canonical docs home — the website.** User-facing documentation lives on
the site. In-repo `docs/` keeps ADRs, handoffs, and development notes;
`docs/simple-mode-limitations.md` (requirement DOC1) was a development aid
and now *feeds* the site's content rather than competing with it. The
sharing recipes promised by requirement E2 become a docs page.
7. **Documentation scope and conventions.** Document the **full supported
feature set**. Any capability not yet fully implemented (a small minority
— e.g. multi-line input, query cancellation, `seed`, `m:n` convenience,
ER-diagram export, the `show tables`/`relationships`/`indexes` family) is
either omitted or carries a clear **"planned / not yet available"**
callout — never presented as shipped. Two wording rules bind all
user-facing copy:
- **No engine name** (SQLite/STRICT/rusqlite/PRAGMA) — continues the
user-facing posture of ADR-0002; copy says "the database"/"the engine".
- **No "DSL"** — it is internal jargon. The two input modes are **simple
mode** (the playground's keyword command language) and **advanced
mode** (SQL).
8. **Install documentation — two mechanisms.** The install page documents
**prebuilt release binaries** (self-hosted download — not GitHub
Releases, since the repo will move) and **package managers**. Both can be
written now against the planned mechanisms; concrete download URLs slot in
at release. (Distribution items D1D3 in `requirements.md` remain the
tracking home for the release tooling itself.)
## Consequences
- The site can ship on the strength of already-implemented features; it is
gated on writing and recording, not on finishing the app.
- One recording format (asciinema `.cast`) serves both marketing and docs,
and is reusable as the app evolves (re-run the script, re-record).
- The WASM playground is preserved as a real future option without holding
up launch; the demo seam keeps the upgrade cheap.
- A single canonical docs home removes the divergence risk of maintaining
user docs in two places.
- Website build choices (Decisions 1, 2, 4, 5) are recorded here for
traceability but do not, by themselves, warrant further ADRs; only
app-architecture decisions (notably the future WASM port) will.
## Out of scope
- **In-page WASM playground** — *deferred* (see Decision 3); revisit as its
own ADR + iteration plan.
- **Hosted/SaaS playground or a server-backed doc CMS** — *rejected*: a
static site fully satisfies the need, consistent with ADR-0007's
no-hosted-publishing stance. Revisit only if real demand emerges.
+7 -1
View File
@@ -3,6 +3,13 @@
This directory contains the project's ADRs, recorded per
[ADR-0000](0000-record-architecture-decisions.md).
> **Website subproject ADRs** live in a separate namespace —
> [`docs/website/adr/`](../website/adr/README.md) — with their own dated
> sequence (`<date>-adr-website-<NNN>.md`, id `ADR-website-NNN`), so they
> never compete with this global integer pool for numbers (see ADR-0000
> "Numbering discipline"). The website itself was decided in
> **ADR-website-001** (formerly ADR-0044 in this index).
## Index
- [ADR-0000 — Record architecture decisions](0000-record-architecture-decisions.md)
@@ -49,4 +56,3 @@ This directory contains the project's ADRs, recorded per
- [ADR-0041 — Copy the output panel to the system clipboard](0041-copy-output-to-clipboard.md) — **Accepted 2026-06-02 (issue #11)**, amends ADR-0003's app-command registry (adds **`copy`** / `copy all` / `copy last`). The friction it removes: filing a bug report meant terminal-selecting the output panel and fighting wrapping/borders. New **app-level command** (sigil-free, both modes): `copy` / `copy all` copy the whole panel; `copy last` copies from the most recent echo line to the end. **Mechanism — OSC 52 *and* native (`arboard`), always both**, because OSC 52 acceptance is undetectable (no terminal ack), so a true "fall back when unsupported" can't be built: emit the OSC 52 escape (no new dep — `base64`+`crossterm`; works over SSH; tmux-passthrough-wrapped via `$TMUX`), then a best-effort native write whose failure is ignored (headless host — OSC 52 carried it); the two carry identical content. **Format — plain text verbatim as rendered** (tags, `✓`/`✗`, box-drawing) joined by `\n`, without viewport padding/wrapping; a drift-lock test pins `OutputLine::plain_text` to `render_output_line`. `arboard` added **`--no-default-features`** (drops the `image` crate; X11-only on Linux — `wayland-data-control` deliberately omitted as it ~doubles the dep tree and OSC 52 covers native-Wayland). Security: write-only, scans clean for arboard's tree (cargo audit / osv-scanner / grype), 1Password-maintained, minimal surface. OOS: Markdown export, selection/range, a keybinding, OSC 52 read, `screen` passthrough
- [ADR-0042 — H1a parse-error pedagogy in the grammar-tree era](0042-h1a-parse-error-pedagogy-grammar-tree.md) — **Accepted 2026-06-03.** Continues **H1a** from ADR-0021 against the ADR-0024 grammar tree (ADR-0021's chumsky mechanism is dead). Records the **baseline already shipped** — per-command `usage:` block (38 `parse.usage.*` templates), available-commands fallback, structural "after `…`, expected …" wording, source-derived ident slot labels ("table name"/"column name"), curated `parse.custom.*` near-miss messages, and the ADR-0027/0033/0036 schema-aware `[ERR]` diagnostics — so H1a is *substantially* delivered at the intent level. Defines the remaining work as **(1)** a verified per-command **near-miss matrix** (`tests/typing_surface/` + `tests/it/parse_error_pedagogy.rs`) as the definition of done, test-first; **(2)** **friendlier literal expectation labels** — optional prose glosses on `Word`/`Punct`/`Flag` positions that *add* role context while always keeping the exact literal visible (e.g. "a filter clause: `where …` or `--all-rows`"); **(3)** **advanced-mode SQL** near-miss parity (RETURNING scope, CTE-arity positioning, `CROSS JOIN … ON`, INSERT…SELECT count) — **in scope**, kept distinct from ADR-0019 §OOS-2 which covers advanced-SQL *engine*-error sanitisation, a different layer. Catalog/anchor-phrase discipline (ADR-0019) preserved; no public API change. OOS: I3/I4, spell-correction, multi-error reporting, verbosity-gating the usage block
- [ADR-0043 — Compound-primary-key foreign-key references (T3)](0043-compound-pk-foreign-key-references.md) — **Accepted + implemented 2026-06-09** (all four forks confirmed at the recommended option: full-PK matching, house-style uniform lists, parenthesized DSL syntax, bare-SQL-FK auto-expansion). Closes `requirements.md` **T3** `[x]` — the relationship model went list-based across six layers (single-column preserved, no migration), DSL `from P.(a,b) to C.(x,y)` + SQL `FOREIGN KEY (a,b) REFERENCES P(x,y)` parse/execute/enforce, 12 tests in `tests/it/compound_fk.rs`. Closes the open leg of `requirements.md` **T3**: a foreign key that *references* a parent's compound primary key. A 2026-06-09 audit found single-column FK woven through ~1520 sites (metadata table, `RelationshipSchema`, `project.yaml` `RawEndpoint`, both grammar surfaces, executor FK-DDL emission, per-column type-compat, display) — earns an ADR, not an inline build. **Decision:** reference the parent's **full** compound PK, matched **positionally** to an equal-length child column list, per-pair `fk_target_type` compat (ADR-0011, element-wise); DSL `from <P>.(a, b) to <C>.(x, y)` (single form unchanged), SQL `FOREIGN KEY (x, y) REFERENCES P(a, b)` (extend the existing one-cap lists; bare table-level FK auto-expands to the parent PK when arities match). **Storage — no migration (back-compat not required, user-confirmed 2026-06-09; no installed base):** the relationship endpoint joins the list convention `project.yaml` *already* uses — `columns: [a, b]` like `primary_key: [id]` and index `columns: [...]` (the endpoint was the lone scalar `column:` holdout); the metadata `TEXT` columns are unchanged and store the list **comma-joined** (`a,b`; the bare name for single — safe because identifiers are `[A-Za-z0-9_]+`). No F3 migrator, no version bump; accepted trade-off is that a pre-change `project.yaml` with relationships won't load (clean cutover). In-memory model goes list-based (`Vec<String>`) through all six layers; the enforced FK is the rebuilt child-table DDL (`FOREIGN KEY (a,b) REFERENCES P(x,y)`), one relationship = one undo step (ADR-0013). Genuine forks escalated: matching policy (full-PK vs subset), storage (house-style uniform lists vs normalized table), DSL syntax (parenthesized vs repeated-dotted), bare-SQL-FK auto-expansion. OOS: subset/non-PK (UNIQUE-targeted) FK references; any single-column behaviour change
- [ADR-0044 — Public website and documentation site](0044-public-website-and-documentation-site.md) — **Accepted 2026-06-04** (originally drafted as ADR-0042 on the `website` branch; renumbered on merge to avoid colliding with the H1a ADR-0042). The first public website: a marketing landing page plus the **canonical** user docs. Stack **Astro 6 + Starlight + Tailwind v4** (chosen over SvelteKit + Tailwind for a docs-heavy + marketing site; interactive bits as Astro islands). Showcase demos are **asciinema** `.cast` recordings (scripted-input driver for paced, re-recordable sessions — *not* `history.log` replay), reused inline in docs. The **in-page WASM playground is deferred** (OOS: deferred) behind a stable `Demo` seam, with the portable-core (`dsl`/`app`/`ui`, in-memory `rusqlite` via `ffi-sqlite-wasm-rs`) vs native-edge (Tokio/worker-thread/`crossterm`/persistence/backup-API) boundary recorded for a future ADR + iteration plan. Portable **static build** (Vercel target, but host-agnostic); **no CI yet**; **monorepo** (`website/`). Docs cover the **full supported feature set** with "planned" callouts for the unshipped minority; two wording rules bind user-facing copy — **no engine name** (continues ADR-0002) and **no "DSL"** ("simple mode" / "advanced mode"). Install docs cover **prebuilt binaries + package managers** (D1D3 track the release tooling). Plan: `docs/plans/20260604-adr-0044-website.md`