"The features didn't change at all. That is the point. When the architecture is the product, you can build the same app twice."
The Day the Workspace Got a Twin
On 2026-09-11 the workspace shipped version 3.0.0 — and v3 is not an update. Every line of the Tauri shell, the Rust core, and the React UI left the tree (317 files, about 65,000 lines), replaced by a Swift-native app: SwiftUI and AppKit, two Swift package targets, no web view anywhere in the product. Put the old build and the new build side by side and the artist cannot tell them apart. That indistinguishability was the acceptance bar — and what it took to clear it is what this lesson is about.
Why Remake a Working App?
The Tauri build was not broken. It was light, stable, and shipped — the lessons before this one taught it for a reason, and they stay in the track for a reason. But the workspace's whole life happens on a Mac, beside Photoshop — and a web view inside a Rust shell is a guest in that house, not a resident. Native menus, the native clipboard, window levels above the host app, a pen tablet's pressure events at the OS layer: each is reachable through a shell, and each is direct in Swift. The decision was never 'Tauri failed.' It was: on this platform, the platform's own language is the lightest shell of all.
The Method: A Replica Beside the Original
You do not rewrite a running product in place. The Swift workspace was born as a separate, isolated project, built in roughly twenty-nine hours beside the running Tauri original — which served as the executable answer key: any question about correct behavior had a running program to ask. Correctness was tracked in a parity ledger: some thirty-five rows, one per behavior — identity, window level, capture, crop, generation, candidates, the paid Pro flow, send/stamp/undo — and no row closed on 'looks right.' A row closed on dated, installed evidence. When the ledger closed, the new tree replaced the old one and the two histories were joined as one repository: old commits and tags preserved, the Tauri source frozen into a legacy archive, nothing force-pushed away.
What Survived the Swap
Remember the survival test from the domain/view lesson: delete the view, and what lives? The remake ran that test for real. Surviving untouched: the bridge protocol (the Photoshop plugin speaks the same envelopes), the workspace domain model — documents, previews, candidates, staleness gates, now a headless Swift core the UI only reads and commands — the lineage contract, and the rule that the app opens no port of its own. Rebuilt: every pixel of the UI and the shell around it. The architecture was the product, so the product survived the stack.
The Kit Underneath
'Native' did not mean 'alone.' The Swift workspace's plumbing — HTTP transport with a chunked reader, the WebSocket client, the local document store, the container paths — comes from the family's shared Swift kit, consumed as one local package dependency. An adoption ledger records which kit revisions are vendored and, just as deliberately, which kit pieces were not adopted: an app-owned JSON type, an app-owned window-placement controller, and no command queue, because a paid generation command must never be replayed. The kit has its own quest; here the point is that going native changed the language, not the discipline of sharing.
The Honest Open Goal
One feature did not make the crossing: precise pen execution — pressure-controlled strokes driven into Photoshop. It was proven once, in the old tree, days before the swap: real timed tablet events, an emergency-stop latch, and a long fight with the OS's secure-input guard. It left with that tree. The new app carries stroke validation and a rehearsal view, and it deliberately does not resurrect the old helper — the retired experiment is evidence to inspect, not an executor to revive. Pen execution stands recorded as the next product goal: open, named, and not implied as done.