History: the Rust/Elixir/Swift → TypeScript cutover (2026-07)#
Context for why decant is a single Bun + TypeScript app and why the project
invariants read the way they do. Written 2026-08-03 from the migration
records.
What existed before#
Until 2026-07-04, decant was three coupled apps: Rust crates (parsers, ingest,
a background daemon that owned the SQLite archive), a Phoenix (Elixir) web
UI talking to the daemon behind a bearer-token API, and a Swift macOS menu
bar app. The pre-cutover tree is preserved in the signed pre-typescript
tag.
The decision#
The stated optimization target was contributor accessibility for AI
developers — one language, one process, one repo-root app. Enabling spikes
happened 2026-07-02 (Bun's bun:sqlite FTS5 support passed; Bun fullstack
HTML imports chosen over Vite so bun build --compile can ship single
binaries embedding the UI). The macOS app was dropped at cutover.
How it landed#
PR #20 carried the entire migration in one PR (284 files, +16k/−40k),
deleting crates/, web/, and macos/; merged to main 2026-07-04 together
with #22 (UI parity). Follow-up audits on 2026-07-04 and 2026-07-06 verified
the punch-list items were resolved in code (server request guards, ingest
test restoration, release workflow, UI parity items).
Durable decisions that trace to the cutover#
- One process owns SQLite (invariant 2): the daemon/token/second-app
architecture is what the cutover removed; do not reintroduce it. - Core modules stay print-free (invariant 1) — output policy lives in
src/cli.ts. - npm distribution uses the optionalDependencies platform-package pattern
(launcher.cjsshim + per-platform compiled binaries) becausenpxruns
under Node while the app needsbun:sqlite. - Toolchain: Bun runtime, Biome, commander, native
fs.watchplus a sweep
(Bun's watcher needed a 2026-04 upstream fix for new subdirectories on
Linux). - The golden-parity oracle (
test/golden/) predates the cutover: it was the
byte-determinism harness proving the TS port matched the Rust behavior, and
it remains the regression net for parser changes.
Useful archaeology pointers#
pre-typescript(signed tag): the last pre-cutover commit; the old Rust
schema tracked versions 1–8 inschema_migrations, which is why pre-v8
archives are rebuild-only today.- The npm scope decision (
@dosu/decant, no plan to claim unscoped
decant) dates to the same period.