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).
6.4 KiB
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 passthroughes 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+ itskeyword/sqlite/all()/from_sql_namealias arms;Value::Blob;CellValue::Blob(Vec<u8>)+ the base64 CSV encode/decode; theBLOB_SLOTgrammar slot; completion'sblobcandidate;output_render'sBLOB; the type-change↔ blobstatic refusal; the seed blob arms; the binder refusal. User-facing strings: droppedblobfromhelp.types_referenceand removed thehint.value_slot_blobslot hint.base64stays (clipboard OSC-52). - Backward-compat migration (the ADR-0015 framework's first real use):
a v1→v2 format bump.
parse_schemahard-pinned the version to 1, so this rippled into aCURRENT_SCHEMA_VERSION = 2constant used by the serializer + parser + skeleton, the first registered migrator (migrate_v1_to_v2: rewritestype: blob→type: text+ bumps the version), and ~30version: 1test fixtures. The runtime (already wired toensure_project_yaml_migrated) forces a.dbrebuild from the migrated text only when a blob column was actually converted (body_declares_blob_columnpre-read at both open sites) — the stale.dbkeeps aSTRICT … BLOBengine 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+ ablobsubstring in a CHECK left untouched); a full-stack integration testtests/it/blob_removal_migration.rs(v1 blob project → migrate →textcolumn + row data preserved +.bak); a Tier-4 PTY end-to-end teste2e_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 +textcolumn) — added in the implementation/rundapass to cover the runtime's migrate-on-open glue; updated all-types tests to nine; regenerated 5 typing-surface snapshots (reviewed — only theblob/datacandidate vanished). - Docs: ADR-0005 Amendment 2 (committed
1a2002d) + README index; sweptten-type→nine-type/ removedblobfrom CLAUDE.md,requirements.md, the website (reference/types.md, the seed doc's stalenot null blobbullet, therdbms.mjshighlight 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/*.csvpast 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. BlobLitgrammar 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_columnmatch the serializer's inline column format (- { name: …, type: … }). A hand-written block-styleproject.yamlwithtype: blobwouldn't convert (and would then fail to parse).project.yamlis 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
blobcontent (type-change matrix,binary/varbinaryaliases) 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). /rundawas 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-migrationparse_schemacallers 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 sweepat 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.