Files
rdbms-playground/docs/handoff/20260622-handoff-79.md
T
claude@clouddev1 6b4c4dcea4
ci / gate (push) Failing after 35s
ci / manifests (push) Successful in 3s
website / deploy (push) Successful in 35s
feat(types)!: drop the blob column type (ADR-0005 Amendment 2)
blob was a dead-end: declarable but never fillable (no literal in either
mode, seed-unsupported), so a blob column could only ever hold NULL. Remove
Type::Blob + Value/CellValue::Blob + the base64 CSV path + the grammar slot
+ completion/render/type-change/seed handling + the binder refusal (whose
message also carried a user-facing "DSL" copy-rule bug). The vocabulary is
now nine types; base64 stays (clipboard OSC-52).

Backward compat is the ADR-0015 migration framework's first real use: a
v1->v2 format bump (CURRENT_SCHEMA_VERSION across serializer/parser/skeleton)
with a migrator that rewrites `type: blob` -> `type: text`, and a forced .db
rebuild from the migrated text when a blob column was actually converted
(the stale .db keeps a STRICT BLOB engine column). Conversion to text is
non-destructive and CSV-free. Covered by a full-stack integration test and a
Tier-4 PTY test that opens a real legacy v1-blob project.

Also sweeps the nine-type vocabulary through CLAUDE.md, requirements.md, the
website (type reference, seed doc, highlight grammar), and the ADR-0030/0033/
0035 cross-references; CHANGELOG Removed entry; handoff-79.

BREAKING CHANGE: the `blob` column type is removed. Existing projects that
declared a blob column are migrated on first open (the column becomes text;
the original project.yaml is kept as a .v1.bak).
2026-06-22 21:25:38 +00:00

108 lines
6.4 KiB
Markdown

# Session handoff — 2026-06-22 (79)
A long session continuing the open-issue sweep (handoff-77/78). Cleared the
**help** issue (#36) and the **schema-cache** bug (#39) earlier; this note
mainly records the big piece: **dropping the `blob` column type** (ADR-0005
Amendment 2), which grew out of a one-line copy-rule fix.
## §1. State
**Branch `main`.** Commits this session so far (all on `main`, **not pushed**):
`07575da` (#39 gate) · `e88fa79` (handoff-77 + changelog rule) · `3ad4aff`
(#36 help) · `64818c0` (handoff-78) · `1a2002d` (**ADR-0005 Amendment 2** —
the blob-drop decision record).
**Uncommitted: the blob-removal implementation** (39 files) — staged for review,
commit proposed at session end (see §4). **Full suite green: 2520 passed / 0
failed / 1 ignored** (1810 lib + 7 e2e_pty + 503 it + 200 typing).
`clippy --all-targets -D warnings` + `fmt --check` clean.
**Closed this session:** #36, #39. **Open:** #37 (clause hints), #38
(diagnostic route — needs a do/defer/close call), #40 (winget release notes).
## §2. What shipped — drop `blob` (ADR-0005 Amendment 2)
**Why** (recorded in the ADR): `blob` was a dead-end type — declarable but
never fillable (no literal in either mode, `seed`-unsupported), so a blob
column could only ever hold NULL. It rode along as the engine's fourth
storage class and never got the pedagogical scrutiny UUIDs (excluded) and
compound PKs (defended) did. The vocabulary is now **nine types**.
**Discovered via:** the `value.rs:106` binder message *"…not supported in DSL
yet"* — a user-facing copy-rule violation (it `passthrough`es to the user via
`DbError::InvalidValue`). Rather than reword, we removed the type; the message
is deleted outright.
**Implementation (test-first throughout):**
- **Removal** (compiler-guided): `Type::Blob` + its `keyword`/`sqlite`/`all()`/
`from_sql_name` alias arms; `Value::Blob`; `CellValue::Blob(Vec<u8>)` + the
base64 CSV encode/decode; the `BLOB_SLOT` grammar slot; completion's `blob`
candidate; `output_render`'s `BLOB`; the type-change `↔ blob` static refusal;
the seed blob arms; the binder refusal. User-facing strings: dropped `blob`
from `help.types_reference` and removed the `hint.value_slot_blob` slot hint.
`base64` **stays** (clipboard OSC-52).
- **Backward-compat migration** (the ADR-0015 framework's **first real use**):
a **v1→v2 format bump**. `parse_schema` hard-pinned the version to 1, so this
rippled into a `CURRENT_SCHEMA_VERSION = 2` constant used by the serializer +
parser + skeleton, the first registered migrator (`migrate_v1_to_v2`:
rewrites `type: blob``type: text` + bumps the version), and ~30 `version: 1`
test fixtures. The runtime (already wired to `ensure_project_yaml_migrated`)
**forces a `.db` rebuild** from the migrated text **only when a blob column
was actually converted** (`body_declares_blob_column` pre-read at both open
sites) — the stale `.db` keeps a `STRICT … BLOB` engine column + `"blob"`
metadata it would otherwise use as-is. Conversion target **text** (not drop)
was the user's call (non-destructive, CSV-free, PK/FK-safe).
- **Tests:** migrator unit tests (incl. a column *named* `blob` + a `blob`
substring in a CHECK left untouched); a **full-stack** integration test
`tests/it/blob_removal_migration.rs` (v1 blob project → migrate → `text`
column + row data preserved + `.bak`); a **Tier-4 PTY** end-to-end test
`e2e_pty::opens_a_legacy_v1_blob_project_by_migrating_to_text` (the real
binary opens a seeded legacy v1-blob project via `--resume` → migrate +
rebuild + `text` column) — added in the implementation `/runda` pass to
cover the runtime's migrate-on-open glue; updated all-types tests to nine;
regenerated 5 typing-surface snapshots (reviewed — only the `blob`/`data`
candidate vanished).
- **Docs:** ADR-0005 Amendment 2 (committed `1a2002d`) + README index; swept
`ten-type``nine-type` / removed `blob` from CLAUDE.md, `requirements.md`,
the website (`reference/types.md`, the seed doc's stale `not null blob`
bullet, the `rdbms.mjs` highlight grammar), and the cross-reference counts in
ADR-0030/0033/0035. CHANGELOG `[Unreleased] → Removed`.
## §3. Decisions & notes for next time
- **convert-to-text, not drop-the-column** (user, 2026-06-22): drop would force
rewriting every `data/*.csv` past the rebuild's strict header check — not
worth it for a few-days-old, few-users tool.
- **Full v2 framework migration, not parse-time leniency** (user): the proper
recorded migration with `.bak`, exercising the dormant framework.
- **`BlobLit` grammar terminal deliberately left** — a pre-existing,
`#[allow(dead_code)]` speculative token never used by any grammar; orthogonal
to the type vocabulary. Its "blob literal" string is unreachable. Removing it
is a separate optional cleanup (touches the grammar core).
- **Known assumption:** the migrator + `body_declares_blob_column` match the
serializer's *inline* column format (`- { name: …, type: … }`). A
hand-written *block-style* `project.yaml` with `type: blob` wouldn't convert
(and would then fail to parse). `project.yaml` is always machine-serialized
inline, so this is fine in practice — noted in case a future format change
moves away from inline columns.
- **Other ADRs (0030/0035) keep their historical `blob` content** (type-change
matrix, `binary`/`varbinary` aliases) per the project's supersede-don't-rewrite
ADR philosophy; ADR-0005 Amendment 2 is the authoritative record.
## §4. Process pins / next
- Commits user-confirmed, no AI attribution, append-only, on `main`; **push is
the user's step** (everything this session is unpushed).
- **`/runda` was run on both the ADR (design) and the implementation.** The
implementation pass found one real gap — the runtime's migrate-on-open glue
was untested — closed with the new Tier-4 PTY test. It also verified the
import path migrates (extract→migrate→rebuild) and the non-migration
`parse_schema` callers fail-safe.
- Proposed commit split for the implementation: (1) `feat(types)!` — code +
tests + CHANGELOG; (2) `docs` — the CLAUDE.md/requirements/website/ADR-x-ref
sweep; (3) `docs(handoff-79)`.
- Consider a `cargo sweep` at this milestone.
- **Next open issues:** #37 (clause hints, on-mission), #38 (escalate
do/defer/close first), #40 (winget release notes). Plus: blob removal means a
`cargo sweep`-worthy build and a good moment to push.