# Disasmer Specification **Status:** draft design spec **Name:** Disasmer, short for **distributed Wasm**. The name intentionally sounds a bit like Wasmer and a bit like “disaster.” **Primary goal:** make distributed execution feel like normal multithreaded programming and normal source-level debugging. Disasmer is a distributed WebAssembly runtime that lets multiple real machines behave like one logical machine. A program runs as one **Virtual Process** with many **Virtual Threads**. Each virtual thread runs on exactly one real machine at a time, but different virtual threads, memory spaces, filesystems, and build tasks may live on different machines. The core promise: ```text Developers debug Disasmer programs like ordinary multithreaded programs. The runtime handles the distributed reality underneath. ``` Disasmer is also intended to support a build-system use case: one build is a virtual process, and build steps are virtual threads/tasks that may run in containers or Nix-defined environments on different operating systems and architectures. --- ## 1. Goals Disasmer should provide: ```text distributed Wasm execution normal VS Code debugging virtual threads across machines distributed/sharded memory spaces cluster-wide suspend/resume per-thread virtual filesystems container/Nix-backed execution environments single-source-file distributed builds explicit artifact publication low-latency reliable control-plane coordination ``` The debugger should see: ```text one process many threads normal stacks normal locals normal source files normal breakpoints normal memory inspection ``` The optional Disasmer inspector may expose distributed internals, but the default debugging experience should remain normal. --- ## 2. Non-goals for the MVP The MVP should not attempt: ```text transparent raw remote pointers live hot-swapping arbitrary Wasm/Rust stack frames checkpointing live sockets checkpointing arbitrary external OS state consensus on every memory access eagerly copying every byte of cluster memory on each breakpoint transparent survival of lost non-replicated nodes full Kubernetes/CI-platform replacement semantics ``` The MVP should favor simple, explicit, debuggable semantics over maximum transparency. --- ## 3. Core terminology ```text Cluster A set of real (or virtual) machines participating in one Disasmer runtime. Coordinator The control-plane entry point for the cluster. Usually reachable through DNS, e.g. cluster.example.com. Node A real machine participating in the cluster. Node Runtime The Disasmer runtime process running on a node. It hosts virtual threads/tasks, memory shards, filesystem data, debug services, environment caches, and node-to-node communication. Virtual Process The logical process seen by the program and debugger. Internally, it may span many nodes. Virtual Thread A debugger-visible logical execution unit. For ordinary Disasmer programs, this is usually a Wasm execution context. For build-system use, it may be backed by a containerized process, sandboxed task, or platform-specific build command. Virtual Task Synonym for Virtual Thread when the unit of work is task-like rather than thread-like. The debugger still sees it as a thread. Memory Space A logical addressable memory region. It may be owned by any node and accessed remotely by other threads. Filesystem Overlay A per-thread writable virtual filesystem layer. Environment Resource A Containerfile, Dockerfile, Nix flake, or equivalent project resource that defines where and how a virtual thread/task should run. Disasmer Bundle / Virtual Binary The packaged executable artifact containing Wasm modules, manifests, debug metadata, environment definitions, and selected input files. Checkpoint A saved execution image containing enough state to resume a virtual thread. Debug Epoch A globally coordinated stopped state used for debugging. ``` --- ## 4. High-level architecture ```text VS Code / Debugger -> DAP / LLDB / custom Disasmer debug adapter -> Disasmer debug endpoint -> Coordinator -> Node Runtimes ``` Cluster connectivity: ```text new node starts -> connects to coordinator through DNS -> authenticates -> receives membership/configuration -> establishes peer links to other nodes ``` Node-to-node communication should prefer: ```text QUIC direct link -> NAT punching where possible -> relay fallback if direct connectivity fails ``` The coordinator is not a hypervisor. It is the **cluster control plane**. It manages membership, identity, placement, debug epochs, metadata, and failure decisions. The data plane should be mostly direct node-to-node traffic. --- ## 5. Project layout and resource discovery Disasmer should make environment resources and input files first-class project resources. Example project: ```text my-project/ src/ main.rs Cargo.toml Cargo.lock envs/ linux/Containerfile windows/Containerfile macos/flake.nix macos/flake.lock inputs/ config.json schema.sql test-data/ example-a.txt example-b.txt disasmer.toml # optional; used only for overrides/disambiguation ``` Default discovery rules: ```text envs//Containerfile -> defines environment of kind container envs//Dockerfile -> defines environment of kind container envs//flake.nix -> defines environment of kind nix-flake inputs/** -> included in the bundle's default VFS seed src/**, Cargo.toml, Cargo.lock -> included for reproducible debugging/building when configured ``` The source code should be able to reference discovered environments by name: ```rust env!("linux") env!("windows") env!("macos") ``` Adding this file: ```text envs/linux/Containerfile ``` should make this possible in source: ```rust spawn::task(compile).env(env!("linux")) ``` No image name, host VM, registry, CI runner, or YAML platform configuration should be required in the source code. --- ## 6. Environment resources An **Environment Resource** defines the execution environment for a virtual thread/task. Supported MVP environment kinds: ```text container Built from Containerfile or Dockerfile. Produces or references an OCI-compatible image or equivalent runtime image. nix-flake Resolved from flake.nix and flake.lock. Produces a reproducible command environment, dev shell, package closure, or runtime root depending on project configuration. ``` Containerfiles and Nix flakes are not identical concepts. Disasmer treats both as ways to produce a normalized **Execution Environment**: ```text Execution Environment name kind digest platform constraints runtime capabilities build/resolution recipe cached materialized form on capable nodes ``` Example normalized environments: ```text environment linux kind: container recipe: envs/linux/Containerfile context: envs/linux digest: sha256:... requires: os=linux, arch=x86_64 environment macos kind: nix-flake recipe: envs/macos/flake.nix lock: envs/macos/flake.lock digest: sha256:... requires: os=macos, arch=arm64 ``` Environment materialization should be cached on nodes: ```text environment digest -> local image / Nix store path / sandbox root ``` The virtual binary should not embed full container images by default. It should embed recipes, manifests, hashes, lock files, and selected context files. Full vendoring should be an explicit mode: ```text disasmer build --vendor-envs ``` Possible vendored data: ```text OCI layers Nix closure prebuilt environment archive ``` --- ## 7. Disasmer bundle / virtual binary A Disasmer bundle is the packaged executable artifact. It contains: ```text Wasm module(s) Wasm component metadata source maps / DWARF / debug metadata Disasmer manifest environment resource manifests selected environment recipe files selected environment context files selected VFS seed files source snapshot when enabled content hashes capability declarations ``` Conceptual bundle layout: ```text app.dis /modules/main.wasm /debug/main.dwarf /manifest/disasmer.json /envs/linux/Containerfile /envs/windows/Containerfile /envs/macos/flake.nix /envs/macos/flake.lock /inputs/config.json /inputs/schema.sql /inputs/test-data/** /source/src/main.rs /source/Cargo.toml /source/Cargo.lock ``` The bundle is content-addressed where possible. Every resource that affects execution should contribute to the bundle digest. The coordinator schedules bundles, not loose files. --- ## 8. Execution model A Disasmer application runs as one **Virtual Process**. A virtual process contains: ```text virtual threads/tasks memory spaces filesystem overlays runtime metadata debug metadata checkpoint metadata environment bindings ``` Each virtual thread runs on exactly one node at a time: ```text thread T1 -> node A thread T2 -> node B thread T3 -> node C ``` A virtual thread may be implemented as: ```text Wasm execution context containerized process sandboxed native process platform-specific build command ``` The debugger sees all of these as threads in one virtual process. Thread placement is based on environment requirements: ```text spawn task with env!("linux") -> coordinator finds a node that can materialize/run environment linux -> node runtime starts the task ``` The source code selects logical environments, not specific machines: ```rust env!("linux") // logical environment ``` Not: ```rust node("builder-17") // real machine, generally not wanted in portable source ``` --- ## 9. Virtual filesystem model Each virtual thread/task receives a virtual filesystem. Default mount model: ```text /vfs/project Read-only source/input snapshot from the bundle. /vfs/work Per-thread writable copy-on-write overlay. /vfs/artifacts Published artifact namespace. /vfs/shared Optional shared namespace with explicit synchronization rules. ``` A thread can create and modify files in its writable overlay. File creation: ```text Thread T creates file F -> T owns the writable version of F -> bytes are physically stored on T's current node by default ``` Flush: ```text fs::flush() -> closes the current write epoch -> publishes filesystem changes -> makes changes visible according to VFS consistency rules ``` Sync: ```text fs::sync() -> makes selected published changes durable/replicated ``` Important distinction: ```text flush = visibility / synchronization point sync = durability / replication point ``` Suspend implicitly performs: ```text flush() checkpoint_thread() optionally sync() ``` Git-like analogy: ```text working tree = thread-local filesystem overlay commit = flush point object store = chunk/blob storage branch/head = latest visible version ``` Disasmer does not need to literally use Git. A content-addressed chunk store is a better internal primitive. --- ## 10. Memory model Disasmer memory is divided into **Memory Spaces**. A memory space has: ```text stable virtual identity address range or handle current owner node version/epoch metadata optional cached pages optional replicas ``` Allocation policy: ```text Memory allocated by a virtual thread is placed on that thread's current node by default. ``` Example: ```text thread T1 running on node A allocates memory M1 -> M1 initially owned by node A thread T2 running on node B allocates memory M2 -> M2 initially owned by node B ``` Remote access is allowed, but mediated by Disasmer. The MVP should not make ordinary raw pointers transparently remote. Instead, distributed state should use explicit Disasmer handles/types: ```rust DBox DArc DMutex DVec DAtomicU64 ``` Local state remains normal language state: ```rust Vec // local to one Wasm context/thread DVec // distributed memory object std::sync::Mutex // local/node/thread concept disasmer::sync::DMutex // distributed synchronization primitive ``` The debugger sees a coherent virtual memory model. Internally, Disasmer maps: ```text virtual memory reference -> memory space -> owner node -> page/chunk -> epoch ``` --- ## 11. Synchronization and consensus The programming model should feel close to normal thread safety: ```text locks atomics happens-before shared mutable memory race conditions linearizable operations ``` The distributed runtime still needs distributed-systems machinery underneath. Consensus/control-plane coordination is used for: ```text cluster membership node identity debug epochs memory ownership metadata thread placement metadata checkpoint ownership filesystem version metadata failure decisions ``` Consensus should not be on the hot path for every load/store. Preferred split: ```text Control plane: consensus-backed metadata Data plane: direct QUIC/RPC between node runtimes owner-based memory protocol leases fencing tokens copy-on-write pages/chunks ``` Every sensitive operation should carry an epoch or fencing token: ```text remote_load(addr, epoch) remote_store(addr, epoch) transfer_memory_owner(space, node, epoch) migrate_thread(thread, node, epoch) debug_freeze(epoch) resume(epoch) ``` --- ## 12. Suspend / resume / checkpoint Disasmer supports suspending a virtual thread. User-facing operation: ```rust suspend().await? ``` Semantics: ```text 1. Reach a safepoint. 2. Stop the virtual thread. 3. Flush the thread filesystem overlay. 4. Snapshot Wasm execution state. 5. Snapshot or reference stack/heap/memory pages. 6. Store checkpoint metadata. 7. Mark thread as PARKED. ``` Resume: ```rust thread.resume().await? ``` Semantics: ```text 1. Select a target node. 2. Fetch checkpoint metadata. 3. Restore Wasm execution state. 4. Restore/mount filesystem overlay. 5. Reconnect memory spaces. 6. Continue execution from a safepoint. ``` The coordinator should store checkpoint metadata, not necessarily all bytes. Actual checkpoint data should live in: ```text node-local storage replicated storage content-addressed blob storage object storage peer-to-peer transferred chunks ``` This enables: ```text thread migration hibernation debug pause/resume load balancing manual relocation fault recovery when state is replicated ``` --- ## 13. Debugging model Debuggability is a primary design requirement. Recommended external interface: ```text VS Code -> DAP -> LLDB / lldb-dap or custom Disasmer adapter -> Disasmer debug endpoint -> Coordinator -> Node Runtimes ``` Disasmer should present the cluster as one virtual debug target. When a breakpoint is hit: ```text 1. A virtual thread hits a breakpoint or trap. 2. Coordinator creates a new Debug Epoch. 3. All node runtimes stop guest execution at safepoints. 4. Memory ownership/migration is frozen. 5. Thread states are collected. 6. Memory pages are pinned copy-on-write. 7. Filesystem overlay versions are pinned. 8. Debugger is told that all threads are stopped. ``` Debugger memory access should be served from a coherent snapshot. Collect eagerly: ```text thread states stacks locals globals memory maps filesystem manifests ``` Collect lazily: ```text heap pages large memory regions filesystem chunks container logs beyond recent tail large artifact data ``` The debugger illusion: ```text Debugger thinks: process P is stopped Reality: cluster is stopped at Debug Epoch E ``` Optional Disasmer inspector: ```text thread -> node thread -> environment memory space -> owner node file -> overlay version artifact -> producer task environment -> digest/cache state remote calls page migrations lock wait graph checkpoint state consensus/control-plane state ``` The default debugger view should remain normal. --- ## 14. VS Code UX Disasmer should provide a VS Code extension. The extension should: ```text watch envs/**/Containerfile watch envs/**/Dockerfile watch envs/**/flake.nix watch envs/**/flake.lock watch inputs/** watch src/** run disasmer build before debugging start or attach to a virtual process bind breakpoints to Wasm/source debug info show virtual threads in the normal debugger thread list show stdout/stderr per virtual thread/task show VFS/artifact state in an optional panel show environment resources as first-class project items provide autocomplete/diagnostics for env!("...") references ``` The intended UX: ```text 1. Add envs/linux/Containerfile. 2. VS Code detects environment "linux". 3. Source autocomplete now accepts env!("linux"). 4. Press F5. 5. Disasmer builds the virtual binary. 6. Disasmer starts the virtual process. 7. VS Code attaches to it as one normal debug target. 8. Breakpoints work across virtual threads/tasks. ``` The extension may generate editor metadata: ```text target/disasmer/generated/envs.rs target/disasmer/generated/resources.json ``` But this generated metadata should not be hand-edited. The project should not require YAML for ordinary usage. Optional `disasmer.toml` may exist for overrides: ```toml [envs.linux] path = "envs/linux/Containerfile" requires = { os = "linux", arch = "x86_64" } [vfs] include = ["inputs/**", "src/**", "Cargo.toml", "Cargo.lock"] exclude = ["target/**", ".git/**"] ``` --- ## 15. Editing source while debugging Disasmer should support a fast edit/restart/debug loop. MVP behavior: ```text source edit -> rebuild bundle -> restart selected virtual task/thread from a clean boundary -> reattach/rebind breakpoints ``` The MVP should not hot-swap arbitrary live code into existing stack frames. Supported restart boundaries: ```text task entrypoint last explicit task checkpoint last published filesystem state last clean build input snapshot ``` Useful VS Code commands: ```text Disasmer: Restart Selected Virtual Thread Disasmer: Restart Failed Task Disasmer: Restart From Last Flush Disasmer: Restart Whole Virtual Process Disasmer: Rebuild Bundle And Rebind Breakpoints ``` Semantics for restarting a selected task: ```text 1. Save source changes. 2. Rebuild the Disasmer bundle. 3. Stop the selected virtual thread/task. 4. Discard unflushed task-local filesystem changes unless configured otherwise. 5. Start the task again using the new bundle version. 6. Mount the same declared environment. 7. Mount the same input/VFS seed or chosen checkpoint boundary. 8. Rebind breakpoints using new debug metadata. ``` The runtime may keep the rest of the virtual process alive only if compatibility checks pass: ```text same public task signatures same serialized argument schema compatible resource manifest compatible memory/handle ABI ``` If compatibility checks fail, the extension should restart the whole virtual process. Design rule: ```text Task restart is an MVP feature. Live code hot-swap is not. ``` --- ## 16. Rust as the primary source language Rust should be the primary guest/source language for Disasmer. Reasons: ```text explicit async boundaries map well to suspend/checkpoint strong types map well to distributed handles macros can register tasks and environments source-level debugging is good one source file can express real build logic ``` C/C++ should be supported later or in parallel as lower-level guest languages, but Rust should define the first-class ergonomic API. Design rule: ```text Local things use normal Rust. Distributed things use Disasmer types. ``` Examples: ```rust Vec // local DVec // distributed std::sync::Mutex // local disasmer::sync::DMutex // distributed std::fs // local/WASI-style filesystem, where supported disasmer::fs // virtual filesystem with flush/sync semantics ``` --- ## 17. Rust API shape The MVP Rust API should be explicit. Example concepts: ```rust #[disasmer::main] async fn main() -> Result<()> { ... } #[disasmer::task] async fn compile(target: Target) -> Result { ... } spawn::task(compile) .arg(Target::LinuxX64) .env(env!("linux")) .start() .await?; ``` The `env!("linux")` macro validates at build time that an environment resource named `linux` exists. The `#[disasmer::task]` macro registers a task entrypoint so it can be started remotely by function identity plus serialized arguments. Task arguments and results should be serializable: ```text arguments -> serialized into task start message results -> serialized into join result handles -> serialized as Disasmer object references ``` --- ## 18. Rust example: multiplatform build in one source file Project layout: ```text example-build/ src/main.rs Cargo.toml Cargo.lock envs/ linux/Containerfile windows/Containerfile macos/flake.nix macos/flake.lock inputs/ build-config.json ``` Source file: ```rust use disasmer::prelude::*; #[derive(Serialize, Deserialize, Clone, Debug)] enum Target { LinuxX64, WindowsX64, MacosArm64, } impl Target { fn name(&self) -> &'static str { match self { Target::LinuxX64 => "linux-x64", Target::WindowsX64 => "windows-x64", Target::MacosArm64 => "macos-arm64", } } fn triple(&self) -> &'static str { match self { Target::LinuxX64 => "x86_64-unknown-linux-gnu", Target::WindowsX64 => "x86_64-pc-windows-msvc", Target::MacosArm64 => "aarch64-apple-darwin", } } fn output_name(&self) -> &'static str { match self { Target::WindowsX64 => "app.exe", _ => "app", } } } #[disasmer::main] async fn main() -> Result<()> { let completed = DAtomicU32::new(0).await?; let linux = spawn::task(compile) .arg(Target::LinuxX64) .arg(completed.clone()) .env(env!("linux")) .start() .await?; let windows = spawn::task(compile) .arg(Target::WindowsX64) .arg(completed.clone()) .env(env!("windows")) .start() .await?; let macos = spawn::task(compile) .arg(Target::MacosArm64) .arg(completed.clone()) .env(env!("macos")) .start() .await?; let linux_artifact = linux.join().await?; let windows_artifact = windows.join().await?; let macos_artifact = macos.join().await?; package(vec![linux_artifact, windows_artifact, macos_artifact]).await?; assert_eq!(completed.load(Ordering::SeqCst).await?, 3); fs::sync().await?; Ok(()) } #[disasmer::task] async fn compile(target: Target, completed: DAtomicU32) -> Result { let target_name = target.name(); let triple = target.triple(); let output_name = target.output_name(); cmd!("cargo", "build", "--release", "--target", triple) .cwd("/vfs/project") .run() .await?; let built_file = format!( "/vfs/project/target/{triple}/release/{output_name}" ); let artifact_file = format!( "/vfs/artifacts/{target_name}/{output_name}" ); fs::copy(&built_file, &artifact_file).await?; // Publish this task's filesystem changes so other tasks can see the artifact. fs::flush().await?; completed.fetch_add(1, Ordering::SeqCst).await?; Ok(Artifact::from_path(artifact_file).await?) } #[disasmer::task] async fn package(outputs: Vec) -> Result<()> { fs::create_dir_all("/vfs/artifacts/dist").await?; for output in outputs { fs::copy(output.path(), "/vfs/artifacts/dist/").await?; } fs::flush().await?; Ok(()) } ``` --- ## 19. What the Rust example does The example defines a complete multiplatform build as one Rust program. It does this: ```text 1. Starts one Disasmer Virtual Process. 2. Creates one distributed atomic counter. 3. Spawns three virtual tasks: - Linux x64 build task - Windows x64 build task - macOS ARM64 build task 4. Places each task into an environment discovered from envs//. 5. Runs each build command in that environment. 6. Copies each produced binary into /vfs/artifacts. 7. Calls fs::flush() to publish each task's artifact. 8. Joins all tasks. 9. Packages all artifacts into /vfs/artifacts/dist. 10. Calls fs::sync() to make final outputs durable. ``` Runtime behavior: ```text env!("linux") -> resolved from envs/linux/Containerfile env!("windows") -> resolved from envs/windows/Containerfile env!("macos") -> resolved from envs/macos/flake.nix + flake.lock spawn compile Linux -> coordinator finds a node capable of running the linux environment -> node runtime materializes/caches the environment -> task runs with its own VFS overlay spawn compile Windows -> coordinator finds a node capable of running the windows environment -> task runs separately but in the same virtual process spawn compile macOS -> coordinator finds a node capable of running the macos environment -> task runs separately but in the same virtual process ``` Debugger behavior: ```text VS Code sees one process: Thread 1: main Thread 2: compile LinuxX64 Thread 3: compile WindowsX64 Thread 4: compile MacosArm64 Thread 5: package ``` The user can set breakpoints in: ```text main() compile() package() ``` When a breakpoint hits, Disasmer enters a Debug Epoch and stops the whole virtual process. --- ## 20. What the Rust example proves The example proves the core Disasmer thesis: ```text A distributed, multiplatform build can be expressed as normal source code, run across different machines/environments, and debugged as one normal multithreaded program. ``` It proves these specific capabilities: ```text one source file can define the build graph Containerfiles/Nix flakes can be project resources, not CI YAML source code can reference environments by logical name virtual tasks can run on different operating systems/architectures artifacts can be published through flush() final outputs can be made durable through sync() shared distributed state can use explicit Disasmer types the debugger can show all tasks as threads of one process ``` It also demonstrates the intended mental model: ```text Build = Virtual Process Build Step = Virtual Thread / Virtual Task Containerfile/Nix flake = Environment Resource Build output = VFS artifact flush() = publish/synchronization point sync() = durability point ``` --- ## 21. What this makes possible Disasmer makes these workflows possible: ```text multiplatform builds without proprietary CI YAML source-level debugging of build logic breakpoints inside distributed build orchestration restart one failed build task after editing source inspect all build tasks in one debugger session share artifacts through a versioned virtual filesystem run Linux/Windows/macOS tasks from one source file mix Wasm orchestration with containerized native commands make distributed execution feel like threaded programming ``` Example VS Code loop: ```text 1. Press F5. 2. Build starts as one virtual process. 3. Windows task fails. 4. Breakpoint/trap stops the virtual process. 5. User edits src/main.rs or project source. 6. User runs "Disasmer: Restart Failed Task". 7. Disasmer rebuilds the bundle. 8. Only the failed task restarts if compatible. 9. Breakpoints are rebound. 10. User continues debugging. ``` This is intentionally different from typical CI systems: ```text not a pile of YAML not tied to one proprietary platform not opaque remote job logs only not separate debuggers per machine ``` --- ## 22. C/C++ support C/C++ should be possible but should not define the primary user experience. C-style API shape: ```c dis_task_t linux = dis_spawn_env("linux", compile_task, &args, sizeof(args)); dis_join(linux); dis_fs_flush(); dis_fs_sync(); ``` Distributed memory in C should use handles: ```c dis_ref_t buffer = dis_mem_alloc(1024); dis_mem_read(buffer, 0, tmp, sizeof(tmp)); dis_mem_write(buffer, 0, data, len); ``` The MVP should not make raw C pointers transparently remote. Rust remains the preferred source language because it gives better type safety, async ergonomics, task registration, and IDE UX. --- ## 23. Failure semantics MVP failure behavior should be simple. If a node with non-replicated guest state is lost: ```text the virtual process is considered crashed ``` If a task is checkpointed and its checkpoint data is durable: ```text the task may be resumed elsewhere ``` If a task has only unflushed local filesystem changes and its node is lost: ```text those unflushed changes are lost ``` If artifacts have been flushed but not synced: ```text they may be visible but not durable ``` If artifacts have been synced: ```text they should survive according to the configured replication policy ``` Do not pretend missing non-replicated state can be debugged. --- ## 24. Security and identity Disasmer should treat cluster identity and bundle identity as core primitives. MVP requirements: ```text nodes authenticate to the coordinator coordinator authorizes nodes for environments/capabilities bundles are content-addressed bundle manifests are signed or integrity-checked environment resources are resolved by digest tasks run with explicit capabilities filesystem access is scoped to the virtual filesystem unless granted network access is explicit per environment/task ``` The source should not casually select real machines by name. It should select logical environments and capabilities. --- ## 25. MVP feature set The MVP should include: ```text Rust SDK #[disasmer::main] #[disasmer::task] env!("name") environment references auto-discovery of envs//Containerfile auto-discovery of envs//Dockerfile auto-discovery of envs//flake.nix bundle manifest generation selected input file bundling per-task VFS overlay fs::flush() fs::sync() spawn task into environment join task basic distributed handles all-stop debugging Debug Epochs lazy memory/filesystem snapshotting VS Code launch/debug extension restart selected task from clean boundary after rebuild QUIC node-to-node transport coordinator-based node discovery ``` MVP restrictions: ```text all-stop debugging only cooperative safepoints only task restart, not live hot-swap explicit distributed types only no transparent raw remote pointers no checkpointing live sockets no automatic survival of non-replicated node loss no eager full-cluster memory copy by default no global consensus on every data operation ``` --- ## 26. Later extensions Possible later extensions: ```text non-stop debugging live code replacement for compatible functions state-schema-aware checkpoint migration replicated memory spaces recoverable distributed locks watchpoints across distributed memory record/replay debugging artifact cache sharing across clusters remote execution marketplace Kubernetes backend cloud worker backend local laptop cluster mode full offline vendored bundles language SDKs for C/C++, Go, Zig, Python/Wasm ``` These are not MVP requirements. --- ## 27. Design summary Disasmer is: ```text a distributed Wasm runtime that presents a cluster as one virtual process with virtual threads/tasks, sharded memory, per-thread virtual filesystems, checkpoint/suspend/resume, container/Nix-backed execution environments, and normal debugger support. ``` For build systems, Disasmer means: ```text Build = Virtual Process Build Step = Virtual Thread / Virtual Task Environment = Containerfile / Dockerfile / Nix flake resource Artifact = VFS-published file Debugger = normal VS Code session ``` The core UX promise: ```text Add a Containerfile or flake.nix to the project. Reference it from Rust with env!("name"). Press F5. Debug the distributed build/program like one normal process. ``` The internal truth: ```text normal debugger illusion backed by cluster-wide debug epochs copy-on-write snapshots node runtimes QUIC peer links distributed memory spaces filesystem overlays checkpoint manifests environment caches and a consensus-backed control plane ```