From 05db9856939167f28136b67c5447a67311ae6d3d Mon Sep 17 00:00:00 2001 From: YifanXu1999 Date: Tue, 27 Oct 2026 01:22:03 +0800 Subject: [PATCH 01/10] test(binding): exercise native behavior outside production source Remove test-only modules and private-helper includes from the Node binding. Replace their eight tests with external Rust tests that load the built addon in Node, using bounded Engine/daemon fixtures. Preserve the forked-child lock regression through a test-only preload fixture; no product API is added. Keep binding integration targets outside the owner-excluded CI lanes. Deleted test locations (all behavior re-covered externally): - discovery.rs::tests::a_dropped_guard_releases_the_lock_while_a_forked_child_holds_a_copy -> tests/native_discovery.rs - tests/unit/admission.rs (2 tests) -> tests/native_admission.rs - tests/unit/reclaim.rs (5 tests) -> tests/native_discovery.rs The public admission deadline test exercises the full 60 s wait; private 300 ms deadline injection is no longer used. Checks: Linux layerfs-node build and tests --no-run; native_discovery 6/6 (30 s ceiling); native_admission 2/2 (90 s ceiling, 60.52 s); node all-target Clippy -D warnings; workspace fmt check; full boundary guard; core/tools unittest suite 63/63 (120 s ceiling); Ruff 0.17.2 format; diff --check. The tests use the registered private Linux Cargo home/target. Node 24 is copied from the pinned runtime image into that target for these checks. No Store profile executes in these fixtures. No production behavior changes. Production LOC: 102158 -> 102158 (delta 0) Scope: all first-party product scopes; core 96788, api 5370, dsh absent. Method: tools/production_loc.py --json from exact parent and staged snapshots; Rust-aware comments and inline test items excluded, shipped SQL and JS included. Counter SHA256: 7e0c3c1ab2fd52895b484c56d18b907cc33b5adbe9a89f8eca77a21ad82b45f0 reference absent (retired R9c; last counted 65,417 at tree 498dd1917812). --- api/binding/src/discovery.rs | 89 ---------- api/binding/src/pool.rs | 4 - api/binding/src/sandbox.rs | 4 - api/binding/tests/README.md | 31 ++++ api/binding/tests/native_admission.rs | 135 +++++++++++++++ api/binding/tests/native_discovery.rs | 149 +++++++++++++++++ api/binding/tests/support/engine.rs | 75 +++++++++ api/binding/tests/support/fork_lock.c | 46 ++++++ api/binding/tests/support/mod.rs | 142 ++++++++++++++++ api/binding/tests/unit/admission.rs | 90 ---------- api/binding/tests/unit/reclaim.rs | 228 -------------------------- core/tools/ci_tests.py | 3 + core/tools/test_ci_tests.py | 22 +++ 13 files changed, 603 insertions(+), 415 deletions(-) create mode 100644 api/binding/tests/README.md create mode 100644 api/binding/tests/native_admission.rs create mode 100644 api/binding/tests/native_discovery.rs create mode 100644 api/binding/tests/support/engine.rs create mode 100644 api/binding/tests/support/fork_lock.c create mode 100644 api/binding/tests/support/mod.rs delete mode 100644 api/binding/tests/unit/admission.rs delete mode 100644 api/binding/tests/unit/reclaim.rs diff --git a/api/binding/src/discovery.rs b/api/binding/src/discovery.rs index ff9c77f1c..c0e058d87 100644 --- a/api/binding/src/discovery.rs +++ b/api/binding/src/discovery.rs @@ -603,92 +603,3 @@ pub(crate) fn save_process(state: &SandboxState, id: &str, p: &Process) -> Resul ]), ) } - -#[cfg(all(test, target_os = "linux"))] -mod tests { - use super::*; - use std::os::{ - fd::{FromRawFd, OwnedFd, RawFd}, - unix::{fs::PermissionsExt, process::CommandExt}, - }; - use std::process::{Command, Stdio}; - extern "C" { - fn pipe2(fds: *mut i32, flags: i32) -> i32; - fn getpid() -> i32; - fn poll(fds: *mut [i32; 2], count: u64, timeout: i32) -> i32; - fn read(fd: i32, buffer: *mut u8, count: usize) -> isize; - fn write(fd: i32, buffer: *const u8, count: usize) -> isize; - fn close(fd: i32) -> i32; - } - const CLOEXEC: i32 = 0o2000000; - const POLLIN: i32 = 1; - - fn pipe() -> (OwnedFd, OwnedFd) { - let mut ends = [0 as RawFd; 2]; - assert_eq!(unsafe { pipe2(ends.as_mut_ptr(), CLOEXEC) }, 0); - unsafe { (OwnedFd::from_raw_fd(ends[0]), OwnedFd::from_raw_fd(ends[1])) } - } - - /// F-053: a child forked while a Guard is held shares the lock's open - /// file description until its exec. Dropping the Guard must release the - /// lock itself, not only this process's descriptor. - #[test] - fn a_dropped_guard_releases_the_lock_while_a_forked_child_holds_a_copy() { - let directory = std::env::temp_dir().join(format!("layerfs-f053-{}", std::process::id())); - let _ = fs::remove_dir_all(&directory); - fs::create_dir(&directory).unwrap(); - fs::set_permissions(&directory, fs::Permissions::from_mode(0o700)).unwrap(); - let (signal_read, signal_write) = pipe(); - let (release_read, release_write) = pipe(); - let (signal, release, release_copy) = ( - signal_write.as_raw_fd(), - release_read.as_raw_fd(), - release_write.as_raw_fd(), - ); - let held = guard(&directory).unwrap(); - // Another thread of the host starts a process meanwhile; its child - // waits between fork and exec with the copied descriptor table. - let spawner = std::thread::spawn(move || { - let mut command = Command::new("true"); - command.stdin(Stdio::null()); - unsafe { - command.pre_exec(move || { - close(release_copy); - let pid = getpid().to_ne_bytes(); - write(signal, pid.as_ptr(), 4); - let mut byte = 0u8; - read(release, &mut byte, 1); - Ok(()) - }); - } - command.spawn().unwrap().wait().unwrap() - }); - // pollfd { fd, events, revents } as two i32 words (events|revents). - let mut poll_fd = [signal_read.as_raw_fd(), POLLIN]; - assert_eq!(unsafe { poll(&mut poll_fd, 1, 10_000) }, 1, "fork signal"); - let mut pid = [0u8; 4]; - assert_eq!( - unsafe { read(signal_read.as_raw_fd(), pid.as_mut_ptr(), 4) }, - 4 - ); - let child = i32::from_ne_bytes(pid); - let lock = directory.join("ownership.lock"); - let copied = fs::read_dir(format!("/proc/{child}/fd")) - .unwrap() - .filter_map(|entry| fs::read_link(entry.ok()?.path()).ok()) - .any(|target| target == lock); - assert!(copied, "child {child} holds no copy of {}", lock.display()); - - drop(held); - // A second open of ownership.lock, as another process would take it. - let taken = os_lock(&directory, std::time::Instant::now()) - .map_err(|refusal| (refusal.code, refusal.message)); - drop(release_write); - assert!(spawner.join().unwrap().success()); - let _ = fs::remove_dir_all(&directory); - assert!( - taken.is_ok(), - "lock still held through the child's copy: {taken:?}" - ); - } -} diff --git a/api/binding/src/pool.rs b/api/binding/src/pool.rs index cd151285a..43781e2fd 100644 --- a/api/binding/src/pool.rs +++ b/api/binding/src/pool.rs @@ -244,7 +244,3 @@ impl DerefMut for Lease<'_> { self.control.as_mut().expect("lent connection") } } - -#[cfg(test)] -#[path = "../tests/unit/admission.rs"] -mod admission_tests; diff --git a/api/binding/src/sandbox.rs b/api/binding/src/sandbox.rs index 7a78db8be..edf23889a 100644 --- a/api/binding/src/sandbox.rs +++ b/api/binding/src/sandbox.rs @@ -500,7 +500,3 @@ pub(crate) fn reclaim(args: &SdkValue, id: &str, container: &str, stopped: bool) ("id", SdkValue::text(id)), ])) } - -#[cfg(test)] -#[path = "../tests/unit/reclaim.rs"] -mod reclaim_tests; diff --git a/api/binding/tests/README.md b/api/binding/tests/README.md new file mode 100644 index 000000000..aaf03096c --- /dev/null +++ b/api/binding/tests/README.md @@ -0,0 +1,31 @@ +# Native binding tests + +> **Status:** Current test guide. + +These Linux tests load the ordinary built addon in Node and call its exported +`call` and `backendCall` methods. They never include private binding source or +add a test-only product API. Build `layerfs-node` first, then compile the test +targets with `--no-run` before running them under an explicit wall timeout: + +```sh +cargo +1.85.1 build --manifest-path core/Cargo.toml --locked -p layerfs-node +cargo +1.85.1 test --manifest-path core/Cargo.toml --locked -p layerfs-node --tests --no-run +timeout 30 cargo +1.85.1 test --manifest-path core/Cargo.toml --locked -p layerfs-node --test native_discovery +timeout 90 cargo +1.85.1 test --manifest-path core/Cargo.toml --locked -p layerfs-node --test native_admission +``` + +Use the worktree's registered Cargo resources for these commands. Node 20 or +later must be available as `node`, or selected by `LAYERFS_TEST_NODE`. The fork +fixture also needs `cc`. Tests locate the addon beside the test executables and +copy it to a private temporary directory with the `.node` suffix Node requires. + +`native_discovery` covers gone and stopped containers, exact refusal custody, +number replacement during inspection, and discovery-lock release while a forked +child retains the descriptor. Its C fixture interposes `flock` only in the child +Node process; the fixture's fork is bounded and released on test unwinding. + +`native_admission` covers initial connection admission and its `Busy` deadline. +The deadline test pays the product's full 60-second readiness wait. The mock +daemon has bounded socket waits and stops independently of a test assertion. +Neither target needs Docker, FUSE, or a Store. The JavaScript API remains outside +the CI lanes under the owner's existing policy; run these targets explicitly. diff --git a/api/binding/tests/native_admission.rs b/api/binding/tests/native_admission.rs new file mode 100644 index 000000000..d4f759846 --- /dev/null +++ b/api/binding/tests/native_admission.rs @@ -0,0 +1,135 @@ +//! First-connection admission through the built Node binding's exported call. +#![cfg(target_os = "linux")] +mod support; +use layerfs_bridge::{ + control::{Answer, DaemonPhase, DaemonStatus, Reply, Request, SdkValue}, + duplex::{accept, generate_keypair}, + initial_record::InitialRecord, +}; +use std::{ + net::TcpListener, + sync::{ + atomic::{AtomicBool, AtomicUsize, Ordering}, + Arc, + }, + thread, + time::{Duration, Instant}, +}; +use support::{engine::*, *}; + +fn run(refuse: Option) { + let home = Home::new(); + let daemon = generate_keypair().unwrap(); + let client = generate_keypair().unwrap(); + home.record(CID, client.private, daemon.public); + let listener = TcpListener::bind("127.0.0.1:0").unwrap(); + let port = listener.local_addr().unwrap().port(); + listener.set_nonblocking(true).unwrap(); + let running = exited() + .replace("\"Running\":false", "\"Running\":true") + .replace( + "\"Ports\":{}", + &format!(r#""Ports":{{"30421/tcp":[{{"HostIp":"127.0.0.1","HostPort":"{port}"}}]}}"#), + ); + let engine = engines(&home.0, vec![(200, running.clone()), (200, running)]); + let ended = Arc::new(AtomicUsize::new(0)); + let count = ended.clone(); + let stopped = Arc::new(AtomicBool::new(false)); + let stop = stopped.clone(); + let server = thread::spawn(move || { + let deadline = Instant::now() + Duration::from_secs(80); + while !stop.load(Ordering::SeqCst) && Instant::now() < deadline { + let stream = match listener.accept() { + Ok((stream, _)) => stream, + Err(e) if e.kind() == std::io::ErrorKind::WouldBlock => { + thread::sleep(Duration::from_millis(2)); + continue; + } + Err(e) => panic!("daemon admission: {e}"), + }; + if refuse.is_none_or(|refuse| count.load(Ordering::SeqCst) < refuse) { + drop(stream); + count.fetch_add(1, Ordering::SeqCst); + continue; + } + stream.set_nonblocking(false).unwrap(); + stream + .set_read_timeout(Some(Duration::from_secs(5))) + .unwrap(); + stream + .set_write_timeout(Some(Duration::from_secs(5))) + .unwrap(); + let mut connection = accept(stream, &daemon.private, client.public).unwrap(); + let hello = match InitialRecord::decode(connection.receive.receive().unwrap()).unwrap() + { + InitialRecord::Control(call) => call, + InitialRecord::Install(_) => panic!("install record"), + }; + assert!(matches!(hello.request, Request::Hello(_))); + connection + .send + .send( + &Answer { + id: hello.id, + reply: Reply::Hello(DaemonStatus { + instance: [7; 32], + phase: DaemonPhase::ControlReady, + overlay_sqlite: Some("3.50.4".into()), + store_sqlite: Some("3.50.4".into()), + }), + } + .encode() + .unwrap(), + ) + .unwrap(); + let call = match InitialRecord::decode(connection.receive.receive().unwrap()).unwrap() { + InitialRecord::Control(call) => call, + InitialRecord::Install(_) => panic!("install record"), + }; + assert!(matches!(call.request, Request::Sdk(_))); + connection + .send + .send( + &Answer { + id: call.id, + reply: Reply::Sdk(SdkValue::map([ + ("kind", SdkValue::text("ok")), + ("workspaces", SdkValue::List(vec![])), + ])), + } + .encode() + .unwrap(), + ) + .unwrap(); + return; + } + }); + let result = std::panic::catch_unwind(|| { + home.node(if refuse.is_some() { + "assert.deepEqual(await native.call('sandbox.list_workspaces',args), {value:{kind:'ok',workspaces:[]}});" + } else { + "const start=Date.now(); const answer=await native.call('sandbox.list_workspaces',args); assert.equal(answer.refused.code,'Busy'); assert.ok(Date.now()-start>=60000);" + }, None, Duration::from_secs(75)) + }); + stopped.store(true, Ordering::SeqCst); + server.join().unwrap(); + assert_eq!(engine.join().unwrap().len(), 2); + if let Err(error) = result { + std::panic::resume_unwind(error); + } + if let Some(refuse) = refuse { + assert_eq!(ended.load(Ordering::SeqCst), refuse); + } else { + assert!(ended.load(Ordering::SeqCst) > 1, "opened only once"); + } +} + +#[test] +fn a_first_connection_waits_for_the_daemon_to_admit_it() { + run(Some(3)); +} + +#[test] +fn a_process_the_daemon_never_admits_is_refused_busy() { + run(None); +} diff --git a/api/binding/tests/native_discovery.rs b/api/binding/tests/native_discovery.rs new file mode 100644 index 000000000..f0afde037 --- /dev/null +++ b/api/binding/tests/native_discovery.rs @@ -0,0 +1,149 @@ +//! External tests of the built Node binding. No private Rust source is included. +#![cfg(target_os = "linux")] +mod support; +use std::{path::Path, process::Command, time::Duration}; +use support::{engine::*, *}; + +#[test] +fn a_gone_container_is_reclaimed_by_removing_its_records() { + let home = Home::new(); + let engine = engine( + &home.0, + 404, + &format!(r#"{{"message":"No such container: {CID}"}}"#), + ); + home.node( + "assert.deepEqual(await reclaim(), {value:{kind:'ok',reclaimed:['1']}});", + None, + Duration::from_secs(5), + ); + assert!(engine + .join() + .unwrap() + .starts_with(&format!("GET /v1.54/containers/{CID}/json"))); + assert!( + !home.0.join("proj/sandboxes/1").exists(), + "its number is free again" + ); +} + +#[test] +fn another_404_is_a_failure_that_removes_nothing() { + let home = Home::new(); + let engine = engine(&home.0, 404, r#"{"message":"page not found"}"#); + home.node( + "assert.equal((await reclaim()).refused.code, 'Failed');", + None, + Duration::from_secs(5), + ); + engine.join().unwrap(); + assert!(home.0.join("proj/sandboxes/1/sandbox.record").exists()); +} + +#[test] +fn a_number_started_again_with_another_container_is_left_alone() { + let home = Home::new(); + let record = home.0.join("proj/sandboxes/1/sandbox.record"); + let engine = engines_before( + &home.0, + vec![(404, format!(r#"{{"message":"No such container: {CID}"}}"#))], + move || { + // The public call read its original record before inspecting it. + let mut bytes = std::fs::read(&record).unwrap(); + let offset = bytes + .windows(64) + .position(|window| window == CID.as_bytes()) + .unwrap(); + bytes[offset..offset + 64].fill(b'c'); + std::fs::write(record, bytes).unwrap(); + }, + ); + home.node( + "assert.deepEqual(await reclaim(), {value:{kind:'ok',reclaimed:[]}});", + None, + Duration::from_secs(5), + ); + engine.join().unwrap(); + let record = std::fs::read(home.0.join("proj/sandboxes/1/sandbox.record")).unwrap(); + assert!(record.windows(64).any(|window| window == [b'c'; 64])); +} + +#[test] +fn a_stopped_container_is_refused_as_gone_then_reclaimed_by_deleting_it() { + let home = Home::new(); + let engine = engines( + &home.0, + vec![(200, exited()), (200, exited()), (204, String::new())], + ); + home.node( + r#" + const first = await native.call('sandbox.list_workspaces', args); + assert.equal(first.refused.code, 'NoSuchSandbox'); + assert.equal(first.refused.detail.containerGone, true); + assert.equal(first.refused.detail.containerStopped, true); + assert.equal(first.refused.detail.container, 'b'.repeat(64)); + assert.deepEqual(await reclaim(), {value:{kind:'ok',reclaimed:['1']}}); + "#, + None, + Duration::from_secs(5), + ); + let requests = engine.join().unwrap(); + assert!(requests[0].starts_with(&format!("GET /v1.54/containers/{CID}/json"))); + assert!(requests[1].starts_with(&format!("GET /v1.54/containers/{CID}/json"))); + assert!(requests[2].starts_with(&format!( + "DELETE /v1.54/containers/{CID}?force=false&v=false" + ))); + assert!( + !home.0.join("proj/sandboxes/1").exists(), + "its number is free again" + ); +} + +#[test] +fn a_stopped_container_the_engine_will_not_delete_keeps_its_records() { + let home = Home::new(); + let engine = engines( + &home.0, + vec![ + (200, exited()), + ( + 409, + r#"{"message":"cannot remove container: container is running"}"#.into(), + ), + ], + ); + home.node( + "assert.equal((await reclaim()).refused.code, 'Failed');", + None, + Duration::from_secs(5), + ); + assert_eq!(engine.join().unwrap().len(), 2); + assert!(home.0.join("proj/sandboxes/1/sandbox.record").exists()); +} + +#[test] +fn a_dropped_guard_releases_the_lock_while_a_forked_child_holds_a_copy() { + let home = Home::new(); + let preload = home.0.join("fork-lock.so"); + assert!(Command::new("cc") + .args(["-shared", "-fPIC", "-Wall", "-Werror"]) + .arg(Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/support/fork_lock.c")) + .args(["-ldl", "-o"]) + .arg(&preload) + .status() + .unwrap() + .success()); + std::fs::remove_file(home.0.join("proj/sandboxes/1/sandbox.record")).unwrap(); + // sandbox.close takes the project guard, then refuses the absent Sandbox. + let call = + "assert.equal((await native.call('sandbox.close',args)).refused.code, 'NoSuchSandbox');"; + home.node(call, Some(&preload), Duration::from_secs(5)); + let child = std::fs::read_to_string(home.0.join("fork.pid")).unwrap(); + let lock = home.0.join("proj/ownership.lock"); + let copied = std::fs::read_dir(format!("/proc/{child}/fd")) + .unwrap() + .filter_map(|entry| std::fs::read_link(entry.ok()?.path()).ok()) + .any(|path| path == lock); + assert!(copied, "child {child} holds no copy of {}", lock.display()); + home.node(call, None, Duration::from_secs(5)); +} diff --git a/api/binding/tests/support/engine.rs b/api/binding/tests/support/engine.rs new file mode 100644 index 000000000..6fb656c2d --- /dev/null +++ b/api/binding/tests/support/engine.rs @@ -0,0 +1,75 @@ +use super::*; +/// The Engine at `home/docker.sock`, answering one request with `status` and `body`. +pub fn engine(home: &Path, status: u16, body: &str) -> JoinHandle { + let engine = engines(home, vec![(status, body.to_owned())]); + thread::spawn(move || engine.join().unwrap().remove(0)) +} + +/// The Engine at `home/docker.sock`, answering each request, one connection +/// each, with the next `(status, body)`; it returns their request heads. +pub fn engines(home: &Path, responses: Vec<(u16, String)>) -> JoinHandle> { + engines_before(home, responses, || {}) +} + +pub fn engines_before( + home: &Path, + responses: Vec<(u16, String)>, + before: impl FnOnce() + Send + 'static, +) -> JoinHandle> { + let listener = UnixListener::bind(home.join("docker.sock")).unwrap(); + listener.set_nonblocking(true).unwrap(); + thread::spawn(move || { + let mut before = Some(before); + let deadline = Instant::now() + Duration::from_secs(3); + let mut requests = Vec::new(); + for (status, body) in responses { + let response = format!( + "HTTP/1.1 {status} test\r\nConnection: close\r\nContent-Type: application/json\r\nContent-Length: {}\r\n\r\n{body}", + body.len() + ); + let stream = loop { + match listener.accept() { + Ok((stream, _)) => break stream, + Err(e) + if e.kind() == std::io::ErrorKind::WouldBlock + && Instant::now() < deadline => + { + thread::sleep(Duration::from_millis(2)) + } + Err(e) => panic!("bounded engine admission: {e}"), + } + }; + stream.set_nonblocking(false).unwrap(); + stream + .set_read_timeout(Some(Duration::from_secs(2))) + .unwrap(); + let mut reader = BufReader::new(stream.try_clone().unwrap()); + let mut request = String::new(); + loop { + let mut line = String::new(); + if reader.read_line(&mut line).unwrap() == 0 || line == "\r\n" { + break; + } + request.push_str(&line); + } + if let Some(before) = before.take() { + before(); + } + (&stream).write_all(response.as_bytes()).unwrap(); + requests.push(request); + } + requests + }) +} + +/// The container's system-call filter as the Engine carries it inside a JSON string. +const SECCOMP: &str = r#"seccomp={\"defaultAction\":\"SCMP_ACT_ALLOW\",\"syscalls\":[{\"names\":[\"unshare\",\"clone\"],\"action\":\"SCMP_ACT_ERRNO\",\"errnoRet\":1,\"args\":[{\"index\":0,\"value\":268435456,\"valueTwo\":268435456,\"op\":\"SCMP_CMP_MASKED_EQ\"}]},{\"names\":[\"clone3\"],\"action\":\"SCMP_ACT_ERRNO\",\"errnoRet\":38}]}"#; + +/// The Engine's inspection of CID after its process exited (Docker +/// restarted): the recorded deployment, intact, not running, no port published. +pub fn exited() -> String { + let image = format!("sha256:{}", "a".repeat(64)); + format!( + r#"{{"Id":"{CID}","Image":"{image}","State":{{"Running":false,"Paused":false,"Restarting":false,"Dead":false}},"Config":{{"User":"0:0","Tty":false,"Entrypoint":["/usr/local/bin/layerfs-daemon"],"Cmd":["--config","/layerfs-local/config/daemon.setup"]}},"HostConfig":{{"Init":true,"Privileged":false,"CapAdd":["CAP_SYS_ADMIN"],"Devices":[{{"PathOnHost":"/dev/fuse","PathInContainer":"/dev/fuse","CgroupPermissions":"rwm"}}],"SecurityOpt":["no-new-privileges=true","apparmor=unconfined","{SECCOMP}"],"RestartPolicy":{{"Name":"no"}},"LogConfig":{{"Type":"json-file"}}}},"Mounts":[{{"Type":"volume","Name":"lfs-test-borrowed","Destination":"/layerfs-store","RW":true,"Driver":"local"}}],"NetworkSettings":{{"Ports":{{}}}}}}"# + ) +} diff --git a/api/binding/tests/support/fork_lock.c b/api/binding/tests/support/fork_lock.c new file mode 100644 index 000000000..899197afb --- /dev/null +++ b/api/binding/tests/support/fork_lock.c @@ -0,0 +1,46 @@ +/* Test-only fork at a real discovery lock acquisition. The child retains the + * open file description while the public binding call drops its Guard. */ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include + +int flock(int fd, int operation) { + int (*original)(int, int) = dlsym(RTLD_NEXT, "flock"); + int result = original(fd, operation); + const char *home = getenv("LAYERFS_FORK_HOME"); + static int forked; + if (result == 0 && operation == (LOCK_EX | LOCK_NB) && home && !forked) { + char link[64], target[4096], expected[4096]; + snprintf(link, sizeof link, "/proc/self/fd/%d", fd); + ssize_t size = readlink(link, target, sizeof target - 1); + if (size < 0) return result; + target[size] = 0; + snprintf(expected, sizeof expected, "%s/proj/ownership.lock", home); + if (strcmp(target, expected) != 0) return result; + forked = 1; + pid_t child = fork(); + if (child < 0) _exit(90); + if (child == 0) { + close(0); close(1); close(2); + char release[4096]; + snprintf(release, sizeof release, "%s/release", home); + for (int i = 0; i < 1000 && access(release, F_OK) != 0; ++i) usleep(10000); + snprintf(release, sizeof release, "%s/fork.done", home); + int done = open(release, O_WRONLY | O_CREAT, 0600); + if (done >= 0) close(done); + _exit(0); + } + char pidfile[4096]; + snprintf(pidfile, sizeof pidfile, "%s/fork.pid", home); + FILE *output = fopen(pidfile, "w"); + if (!output) _exit(91); + fprintf(output, "%d", child); + fclose(output); + } + return result; +} diff --git a/api/binding/tests/support/mod.rs b/api/binding/tests/support/mod.rs new file mode 100644 index 000000000..bdc572e09 --- /dev/null +++ b/api/binding/tests/support/mod.rs @@ -0,0 +1,142 @@ +#![allow(dead_code)] +use layerfs_bridge::control::{Answer, Reply, SdkValue}; +use std::{ + io::{BufRead, BufReader, Write}, + os::unix::{ + fs::{DirBuilderExt, OpenOptionsExt}, + net::UnixListener, + }, + path::{Path, PathBuf}, + process::{Command, Stdio}, + sync::atomic::{AtomicUsize, Ordering}, + thread::{self, JoinHandle}, + time::{Duration, Instant}, +}; + +pub mod engine; +pub const CID: &str = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"; +static NEXT: AtomicUsize = AtomicUsize::new(0); + +pub struct Home(pub PathBuf); +impl Home { + pub fn new() -> Self { + let root = std::env::temp_dir().join(format!( + "layerfs-binding-{}-{}", + std::process::id(), + NEXT.fetch_add(1, Ordering::Relaxed) + )); + for path in [ + root.clone(), + root.join("proj"), + root.join("proj/sandboxes"), + root.join("proj/sandboxes/1"), + ] { + std::fs::DirBuilder::new().mode(0o700).create(path).unwrap(); + } + let artifact = std::env::current_exe() + .unwrap() + .parent() + .unwrap() + .parent() + .unwrap() + .join("liblayerfs_node.so"); + std::fs::copy(artifact, root.join("layerfs.node")) + .expect("build layerfs-node before running native tests"); + let home = Self(root); + home.record(CID, [1; 32], [2; 32]); + home + } + + pub fn record(&self, container: &str, secret: [u8; 32], peer: [u8; 32]) { + let bytes = |n: [u8; 32]| SdkValue::Bytes(n.to_vec()); + let value = SdkValue::map([ + ("id", SdkValue::text("1")), + ("project", SdkValue::text("proj")), + ("container", SdkValue::text(container)), + ( + "docker", + SdkValue::text(self.0.join("docker.sock").to_str().unwrap()), + ), + ( + "image", + SdkValue::text(format!("sha256:{}", "a".repeat(64))), + ), + ("volume", SdkValue::text("lfs-test-borrowed")), + ("secret", bytes(secret)), + ("peer", bytes(peer)), + ("instance", bytes([7; 32])), + ]); + let path = self.0.join("proj/sandboxes/1/sandbox.record"); + let mut file = std::fs::OpenOptions::new() + .write(true) + .create(true) + .truncate(true) + .mode(0o600) + .open(path) + .unwrap(); + file.write_all( + &Answer { + id: 1, + reply: Reply::Sdk(value), + } + .encode() + .unwrap(), + ) + .unwrap(); + } + + pub fn node(&self, script: &str, preload: Option<&Path>, timeout: Duration) { + let mut command = + Command::new(std::env::var_os("LAYERFS_TEST_NODE").unwrap_or_else(|| "node".into())); + command + .arg("-e") + .arg(format!( + r#" + const assert = require('node:assert/strict'); + const native = require(process.env.LAYERFS_NATIVE); + const args = {{home: process.env.LAYERFS_HOME, project:'proj', sandbox:'1'}}; + const reclaim = () => native.backendCall('runtime.sandbox.reclaim', args); + (async () => {{ {script} }})().catch(e => {{ console.error(e); process.exitCode=1; }}); + "# + )) + .env("LAYERFS_NATIVE", self.0.join("layerfs.node")) + .env("LAYERFS_HOME", &self.0) + .stdout(Stdio::inherit()) + .stderr(Stdio::inherit()); + if let Some(preload) = preload { + command + .env("LD_PRELOAD", preload) + .env("LAYERFS_FORK_HOME", &self.0); + } + let mut child = command.spawn().unwrap(); + let deadline = Instant::now() + timeout; + let status = loop { + if let Some(status) = child.try_wait().unwrap() { + break status; + } + if Instant::now() >= deadline { + child.kill().unwrap(); + child.wait().unwrap(); + panic!("native binding call exceeded {timeout:?}"); + } + thread::sleep(Duration::from_millis(2)); + }; + assert!(status.success(), "Node binding assertions failed: {status}"); + } +} +impl Drop for Home { + fn drop(&mut self) { + // The fork fixture observes this even during panic unwinding. + let _ = std::fs::write(self.0.join("release"), b"release"); + if self.0.join("fork.pid").exists() { + let deadline = Instant::now() + Duration::from_secs(1); + while !self.0.join("fork.done").exists() && Instant::now() < deadline { + thread::sleep(Duration::from_millis(2)); + } + if !self.0.join("fork.done").exists() { + return; + } + } + let _ = std::fs::remove_dir_all(&self.0); + } +} diff --git a/api/binding/tests/unit/admission.rs b/api/binding/tests/unit/admission.rs deleted file mode 100644 index a98f3c6b4..000000000 --- a/api/binding/tests/unit/admission.rs +++ /dev/null @@ -1,90 +0,0 @@ -//! A process whose first connection the daemon does not admit, because -//! other processes hold every connection it admits, waits to be admitted -//! instead of failing with a bare `UnexpectedEof`, and is refused `Busy` -//! once the wait ends. Included by pool.rs. -use super::Dial; -use layerfs_bridge::control::{Answer, DaemonPhase, DaemonStatus, Reply, Request}; -use layerfs_bridge::duplex::{accept, generate_keypair}; -use layerfs_bridge::initial_record::InitialRecord; -use std::{ - net::TcpListener, - sync::{ - atomic::{AtomicUsize, Ordering}, - Arc, - }, - thread, - time::{Duration, Instant}, -}; - -const INSTANCE: [u8; 32] = [7; 32]; - -/// A daemon that ends its first `refuse` sockets unread, as the daemon ends -/// a socket while it has no vacant connection slot, then admits the next one -/// and answers its Hello; `None` admits none. Counts the sockets it ended. -fn daemon(refuse: Option) -> (Dial, Arc, thread::JoinHandle<()>) { - let daemon = generate_keypair().unwrap(); - let client = generate_keypair().unwrap(); - let listener = TcpListener::bind("127.0.0.1:0").unwrap(); - let dial = Dial { - endpoint: listener.local_addr().unwrap(), - host: None, - secret: client.private, - peer: daemon.public, - instance: INSTANCE, - }; - let ended = Arc::new(AtomicUsize::new(0)); - let count = ended.clone(); - let server = thread::spawn(move || loop { - let (stream, _) = listener.accept().unwrap(); - if refuse.is_none_or(|refuse| count.load(Ordering::SeqCst) < refuse) { - drop(stream); - count.fetch_add(1, Ordering::SeqCst); - continue; - } - stream - .set_read_timeout(Some(Duration::from_secs(10))) - .unwrap(); - let mut connection = accept(stream, &daemon.private, client.public).unwrap(); - let call = match InitialRecord::decode(connection.receive.receive().unwrap()).unwrap() { - InitialRecord::Control(call) => call, - InitialRecord::Install(_) => panic!("install record"), - }; - assert!(matches!(call.request, Request::Hello(_)), "{call:?}"); - let answer = Answer { - id: call.id, - reply: Reply::Hello(DaemonStatus { - instance: INSTANCE, - phase: DaemonPhase::ControlReady, - overlay_sqlite: Some("3.50.4".into()), - store_sqlite: Some("3.50.4".into()), - }), - }; - connection.send.send(&answer.encode().unwrap()).unwrap(); - return; - }); - (dial, ended, server) -} - -#[test] -fn a_first_connection_waits_for_the_daemon_to_admit_it() { - let (dial, ended, server) = daemon(Some(3)); - if let Err(refusal) = dial.open_waiting() { - panic!("not admitted: {}: {}", refusal.code, refusal.message); - } - server.join().unwrap(); - assert_eq!(ended.load(Ordering::SeqCst), 3); -} - -#[test] -fn a_process_the_daemon_never_admits_is_refused_busy() { - let (dial, ended, _server) = daemon(None); - let started = Instant::now(); - let refusal = dial - .open_admitted(Duration::from_millis(300)) - .map(|_| ()) - .unwrap_err(); - assert_eq!(refusal.code, "Busy", "{}", refusal.message); - assert!(started.elapsed() >= Duration::from_millis(300)); - assert!(started.elapsed() < Duration::from_secs(10)); - assert!(ended.load(Ordering::SeqCst) > 1, "opened only once"); -} diff --git a/api/binding/tests/unit/reclaim.rs b/api/binding/tests/unit/reclaim.rs deleted file mode 100644 index 437c999cd..000000000 --- a/api/binding/tests/unit/reclaim.rs +++ /dev/null @@ -1,228 +0,0 @@ -//! #373: a Sandbox whose container the Engine no longer has, or has -//! stopped, is reclaimed (a stopped container deleted once, then its -//! records) so its number is free again; nothing else counts as gone. -//! Included by sandbox.rs. -use super::reclaim; -use layerfs_bridge::control::SdkValue; -use std::{ - io::{BufRead, BufReader, Write}, - os::unix::{fs::DirBuilderExt, net::UnixListener}, - path::{Path, PathBuf}, - sync::atomic::{AtomicUsize, Ordering}, - thread::{self, JoinHandle}, - time::{Duration, Instant}, -}; - -const CID: &str = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"; -const ID: &str = "1"; -static NEXT: AtomicUsize = AtomicUsize::new(0); - -/// A private LayerFS home with Sandbox 1 of project `proj` recorded as -/// running in container CID, behind the Engine socket `docker.sock`. -fn home() -> PathBuf { - let home = std::env::temp_dir().join(format!( - "layerfs-reclaim-{}-{}", - std::process::id(), - NEXT.fetch_add(1, Ordering::Relaxed) - )); - let private = |path: &Path| std::fs::DirBuilder::new().mode(0o700).create(path).unwrap(); - private(&home); - private(&home.join("proj")); - private(&home.join("proj").join("sandboxes")); - private(&dir(&home)); - let bytes = |n: u8| SdkValue::Bytes(vec![n; 32]); - crate::discovery::save( - &dir(&home).join("sandbox.record"), - SdkValue::map([ - ("id", SdkValue::text(ID)), - ("project", SdkValue::text("proj")), - ("container", SdkValue::text(CID)), - ( - "docker", - SdkValue::text(home.join("docker.sock").to_str().unwrap()), - ), - ( - "image", - SdkValue::text(format!("sha256:{}", "a".repeat(64))), - ), - ("volume", SdkValue::text("lfs-test-borrowed")), - ("secret", bytes(1)), - ("peer", bytes(2)), - ("instance", bytes(3)), - ]), - ) - .unwrap(); - home -} - -/// Sandbox 1's directory. -fn dir(home: &Path) -> PathBuf { - home.join("proj").join("sandboxes").join(ID) -} - -/// The Engine at `home/docker.sock`, answering one request with `status` and `body`. -fn engine(home: &Path, status: u16, body: &str) -> JoinHandle { - let engine = engines(home, vec![(status, body.to_owned())]); - thread::spawn(move || engine.join().unwrap().remove(0)) -} - -/// The Engine at `home/docker.sock`, answering each request, one connection -/// each, with the next `(status, body)`; it returns their request heads. -fn engines(home: &Path, responses: Vec<(u16, String)>) -> JoinHandle> { - let listener = UnixListener::bind(home.join("docker.sock")).unwrap(); - listener.set_nonblocking(true).unwrap(); - thread::spawn(move || { - let deadline = Instant::now() + Duration::from_secs(3); - let mut requests = Vec::new(); - for (status, body) in responses { - let response = format!( - "HTTP/1.1 {status} test\r\nConnection: close\r\nContent-Type: application/json\r\nContent-Length: {}\r\n\r\n{body}", - body.len() - ); - let stream = loop { - match listener.accept() { - Ok((stream, _)) => break stream, - Err(e) - if e.kind() == std::io::ErrorKind::WouldBlock - && Instant::now() < deadline => - { - thread::sleep(Duration::from_millis(2)) - } - Err(e) => panic!("bounded engine admission: {e}"), - } - }; - stream.set_nonblocking(false).unwrap(); - stream - .set_read_timeout(Some(Duration::from_secs(2))) - .unwrap(); - let mut reader = BufReader::new(stream.try_clone().unwrap()); - let mut request = String::new(); - loop { - let mut line = String::new(); - if reader.read_line(&mut line).unwrap() == 0 || line == "\r\n" { - break; - } - request.push_str(&line); - } - (&stream).write_all(response.as_bytes()).unwrap(); - requests.push(request); - } - requests - }) -} - -/// The container's system-call filter as the Engine carries it inside a JSON string. -const SECCOMP: &str = r#"seccomp={\"defaultAction\":\"SCMP_ACT_ALLOW\",\"syscalls\":[{\"names\":[\"unshare\",\"clone\"],\"action\":\"SCMP_ACT_ERRNO\",\"errnoRet\":1,\"args\":[{\"index\":0,\"value\":268435456,\"valueTwo\":268435456,\"op\":\"SCMP_CMP_MASKED_EQ\"}]},{\"names\":[\"clone3\"],\"action\":\"SCMP_ACT_ERRNO\",\"errnoRet\":38}]}"#; - -/// The Engine's inspection of CID after its process exited (Docker -/// restarted): the recorded deployment, intact, not running, no port published. -fn exited() -> String { - let image = format!("sha256:{}", "a".repeat(64)); - format!( - r#"{{"Id":"{CID}","Image":"{image}","State":{{"Running":false,"Paused":false,"Restarting":false,"Dead":false}},"Config":{{"User":"0:0","Tty":false,"Entrypoint":["/usr/local/bin/layerfs-daemon"],"Cmd":["--config","/layerfs-local/config/daemon.setup"]}},"HostConfig":{{"Init":true,"Privileged":false,"CapAdd":["CAP_SYS_ADMIN"],"Devices":[{{"PathOnHost":"/dev/fuse","PathInContainer":"/dev/fuse","CgroupPermissions":"rwm"}}],"SecurityOpt":["no-new-privileges=true","apparmor=unconfined","{SECCOMP}"],"RestartPolicy":{{"Name":"no"}},"LogConfig":{{"Type":"json-file"}}}},"Mounts":[{{"Type":"volume","Name":"lfs-test-borrowed","Destination":"/layerfs-store","RW":true,"Driver":"local"}}],"NetworkSettings":{{"Ports":{{}}}}}}"# - ) -} - -fn args(home: &Path) -> SdkValue { - SdkValue::map([ - ("sandbox", SdkValue::text(ID)), - ("project", SdkValue::text("proj")), - ("home", SdkValue::text(home.to_str().unwrap())), - ]) -} - -/// Reopens Sandbox 1 and, when it is gone, reclaims it, as `sandbox.create` does. -fn place(home: &Path) -> Result { - let refusal = crate::discovery::reopen(&args(home)) - .err() - .expect("not running"); - match crate::discovery::gone_container(&refusal) { - Some((container, stopped)) => reclaim(&args(home), ID, container, stopped), - None => Err(refusal), - } -} - -#[test] -fn a_gone_container_is_reclaimed_by_removing_its_records() { - let home = home(); - let engine = engine( - &home, - 404, - &format!(r#"{{"message":"No such container: {CID}"}}"#), - ); - let closed = place(&home).unwrap(); - assert_eq!(closed.get_text("kind"), Some("Reclaimed")); - assert_eq!(closed.get_text("id"), Some(ID)); - assert!(engine - .join() - .unwrap() - .starts_with(&format!("GET /v1.54/containers/{CID}/json"))); - assert!(!dir(&home).exists(), "its number is free again"); - std::fs::remove_dir_all(home).unwrap(); -} - -#[test] -fn another_404_is_a_failure_that_removes_nothing() { - let home = home(); - let engine = engine(&home, 404, r#"{"message":"page not found"}"#); - let refusal = place(&home).unwrap_err(); - assert_eq!(refusal.code, "Failed"); - engine.join().unwrap(); - assert!(dir(&home).join("sandbox.record").exists()); - std::fs::remove_dir_all(home).unwrap(); -} - -#[test] -fn a_number_started_again_with_another_container_is_left_alone() { - let home = home(); - let other = "c".repeat(64); - let refusal = reclaim(&args(&home), ID, &other, false).unwrap_err(); - assert_eq!(refusal.code, "Busy"); - assert!(dir(&home).join("sandbox.record").exists()); - std::fs::remove_dir_all(home).unwrap(); -} - -#[test] -fn a_stopped_container_is_refused_as_gone_then_reclaimed_by_deleting_it() { - let home = home(); - let engine = engine(&home, 200, &exited()); - let refusal = crate::discovery::reopen(&args(&home)).err().unwrap(); - engine.join().unwrap(); - assert_eq!(refusal.code, "NoSuchSandbox"); - assert!(matches!( - refusal.detail.get("containerGone"), - Some(SdkValue::Bool(true)) - )); - assert!(matches!( - refusal.detail.get("containerStopped"), - Some(SdkValue::Bool(true)) - )); - assert_eq!( - crate::discovery::gone_container(&refusal), - Some((CID, true)) - ); - - std::fs::remove_file(home.join("docker.sock")).unwrap(); - let engine = engines(&home, vec![(200, exited()), (204, String::new())]); - let closed = place(&home).unwrap(); - assert_eq!(closed.get_text("kind"), Some("Reclaimed")); - let requests = engine.join().unwrap(); - assert!(requests[0].starts_with(&format!("GET /v1.54/containers/{CID}/json"))); - assert!(requests[1].starts_with(&format!( - "DELETE /v1.54/containers/{CID}?force=false&v=false" - ))); - assert!(!dir(&home).exists(), "its number is free again"); - std::fs::remove_dir_all(home).unwrap(); -} - -#[test] -fn a_stopped_container_the_engine_will_not_delete_keeps_its_records() { - let home = home(); - let running = r#"{"message":"cannot remove container: container is running"}"#; - let engine = engines(&home, vec![(200, exited()), (409, running.to_owned())]); - let refusal = place(&home).unwrap_err(); - assert_eq!(refusal.code, "Failed"); - assert_eq!(engine.join().unwrap().len(), 2); - assert!(dir(&home).join("sandbox.record").exists()); - std::fs::remove_dir_all(home).unwrap(); -} diff --git a/core/tools/ci_tests.py b/core/tools/ci_tests.py index e981a9254..fb70b673c 100644 --- a/core/tools/ci_tests.py +++ b/core/tools/ci_tests.py @@ -87,6 +87,9 @@ def metadata(): def test_targets(meta): """Yield (package, target, source path) for every integration test target.""" for package in meta["packages"]: + # The owner leaves the JavaScript API out of both CI lanes. + if package["name"] == "layerfs-node": + continue for target in package["targets"]: if "test" in target["kind"]: yield package["name"], target["name"], Path(target["src_path"]) diff --git a/core/tools/test_ci_tests.py b/core/tools/test_ci_tests.py index dffad6749..29090aac7 100644 --- a/core/tools/test_ci_tests.py +++ b/core/tools/test_ci_tests.py @@ -47,6 +47,28 @@ def test_fast_filter_excludes_the_nightly_groups_and_nightly_selects_them(self): class ExecutablesFromCargoJson(unittest.TestCase): + def test_binding_tests_stay_out_of_the_ci_lanes(self): + meta = { + "packages": [ + { + "name": "layerfs-node", + "targets": [ + { + "name": "native_discovery", + "kind": ["test"], + "src_path": "/w/api/binding/tests/native_discovery.rs", + }, + { + "name": "native_admission", + "kind": ["test"], + "src_path": "/w/api/binding/tests/native_admission.rs", + }, + ], + } + ] + } + self.assertEqual(list(ci_tests.test_targets(meta)), []) + def test_keeps_only_mount_test_binaries(self): meta = {"packages": [{"name": "layerfs-daemon", "manifest_path": "/w/core/crates/layerfs-daemon/Cargo.toml"}]} From 2775b3fa44512841d5cb25fd0942cc7e9ebe83eb Mon Sep 17 00:00:00 2001 From: YifanXu1999 Date: Tue, 27 Oct 2026 01:22:45 +0800 Subject: [PATCH 02/10] refactor(463): enforce crate layers in the product boundary guard Map all Rust crates (including layerfs-node) to core, engine and api. Check production/build/dev edges, target-table aliases, resolved test path includes, and the core rusqlite ban. Unknown crates fail closed. Keep layout knowledge in one crate-root helper and preserve the production edge allowlist. Temporary exception: daemon -> api dev dependency and only the six includes from merge_report, concurrent_commits and lane_merge to the two named API helpers. Step 2b removes the exception. DOMAIN_CRATES is unchanged for step 1. G1: owner instructed proceeding with MIGRATION_SPEC.md; D8 accepted. Subsequent owner answers allow project -> bridge, select engine, and authorize relocation once branch conflicts are resolved. No push, PR or merge is authorized. Checks: full-tree boundary guard PASS (953 production inputs); core/tools unittest discovery 63/63 PASS under 120 s timeout (includes all guard tests); Ruff 0.17.2 format and check PASS; git diff --check PASS. Tooling only; Rust compilation/runtime tests are inapplicable to this step. No tests deleted. The binding prerequisite is commit 05db985693. Production LOC: 102158 -> 102158 (delta 0) Scope: all first-party product scopes, core 96788 and api 5370; dsh absent. Method: tools/production_loc.py --json from exact parent and staged snapshots; Rust-aware comments/inline tests excluded, shipped SQL and JS included. Counter SHA256: 7e0c3c1ab2fd52895b484c56d18b907cc33b5adbe9a89f8eca77a21ad82b45f0 reference absent (retired R9c; last counted 65,417 at tree 498dd1917812). --- core/tools/check_product_boundary.py | 116 +++++++++++++++++++--- core/tools/test_check_product_boundary.py | 87 +++++++++++++++- 2 files changed, 184 insertions(+), 19 deletions(-) diff --git a/core/tools/check_product_boundary.py b/core/tools/check_product_boundary.py index 30c246e39..3f1b2b047 100644 --- a/core/tools/check_product_boundary.py +++ b/core/tools/check_product_boundary.py @@ -1,10 +1,9 @@ """Small source-text guard for core/AGENTS.md; semantic review is still required.""" -from pathlib import Path import re import sys import tomllib - +from pathlib import Path ATTR = re.compile(r"#\s*!?\s*\[([^\]]*)\]", re.DOTALL) TEST_ATTR = re.compile(r"^(?:\w+\s*::\s*)*(?:test|bench)\b") @@ -58,6 +57,16 @@ # First-party production edges; third-party approvals and the locked graph are # checked separately. The combined SQLite adapter is the active provider. ALLOWED_DEPENDENCIES = { + "layerfs-node": { + "layerfs-api", + "layerfs-bridge", + "layerfs-history", + "layerfs-persistence", + "layerfs-sandbox", + "layerfs-storage", + "layerfs-store-service", + "layerfs-telemetry", + }, "layerfs-telemetry": set(), "layerfs-content": {"layerfs-telemetry"}, "layerfs-storage": {"layerfs-content", "layerfs-telemetry"}, @@ -108,6 +117,71 @@ "layerfs-sandbox": set(), } DOMAIN_CRATES = {"layerfs-content", "layerfs-storage", "layerfs-history", "layerfs-project"} +LAYER_ORDER = ("core", "engine", "api") +CORE, ENGINE, API = LAYER_ORDER +LAYER = { + "layerfs-content": CORE, + "layerfs-history": CORE, + "layerfs-storage": CORE, + "layerfs-telemetry": CORE, + "layerfs-bridge": ENGINE, + "layerfs-daemon": ENGINE, + "layerfs-fuse": ENGINE, + "layerfs-overlay": ENGINE, + "layerfs-persistence": ENGINE, + "layerfs-project": ENGINE, + "layerfs-sandbox": ENGINE, + "layerfs-store-service": ENGINE, + "layerfs-workspace": ENGINE, + "layerfs-api": API, + "layerfs-node": API, +} +# Temporary upward test link; migration #463 step 2b removes both exceptions. +UPWARD_TEST_EDGE = ("layerfs-daemon", "layerfs-api") +UPWARD_TEST_PATHS = { + (f"tests/{test}.rs", f"tests/support/{helper}.rs") + for test in ("merge_report", "concurrent_commits", "lane_merge") + for helper in ("installed_store", "sdk") +} + + +def layer_violations(name, dependency, kind): + if dependency.startswith("layerfs-") and dependency not in LAYER: + return [(1, f"crate missing from layer map: {dependency}")] + if dependency in LAYER and LAYER_ORDER.index(LAYER[dependency]) > LAYER_ORDER.index(LAYER[name]): + if kind == "dev-dependencies" and (name, dependency) == UPWARD_TEST_EDGE: + return [] + return [(1, f"upward {kind} edge {name} ({LAYER[name]}) -> {dependency} ({LAYER[dependency]})")] + return [] + + +def crate_directories(core): + """All Rust crate roots; keep layout knowledge in one helper.""" + return sorted(path for path in (core / "crates").glob("*") if path.is_dir()) + [core.parent / "api/binding"] + + +def test_path_violations(path, source, packages): + """Resolve test includes before checking their owning crate's layer.""" + packages = {root.resolve(): name for root, name in packages.items()} + path = path.resolve() + owner = next((root for root in packages if path.is_relative_to(root)), None) + if owner is None or packages[owner] not in LAYER: + return [] + found = [] + for match in re.finditer(r'#\s*\[\s*path\s*=\s*"([^"]+)"\s*\]', source): + target = (path.parent / match[1]).resolve() + destination = next((root for root in packages if target.is_relative_to(root)), None) + if destination is None: + continue + name, dependency = packages[owner], packages[destination] + exception = (path.relative_to(owner).as_posix(), target.relative_to(destination).as_posix()) + if (name, dependency) == UPWARD_TEST_EDGE and exception in UPWARD_TEST_PATHS: + continue + for _, reason in layer_violations(name, dependency, "test #[path]"): + found.append((source.count("\n", 0, match.start()) + 1, reason)) + return found + + ENGINES_AND_CLUSTER2 = { "layerfs-s3", "layerfs-metadata", @@ -141,20 +215,26 @@ def dependency_violations(source): - """Check production/build edges, including target tables and aliases.""" + """Check production/build and test edges, including target tables and aliases.""" manifest = tomllib.loads(source) name = manifest.get("package", {}).get("name") if name in RETIRED_PACKAGES: return [(1, f"{RETIRED_PACKAGE}: {name}")] - if name not in ALLOWED_DEPENDENCIES: - return [] - sections = [manifest.get(key, {}) for key in ("dependencies", "build-dependencies")] + if name not in LAYER: + return [(1, f"crate missing from layer map: {name}")] + kinds = ("dependencies", "build-dependencies", "dev-dependencies") + sections = [(key, manifest.get(key, {})) for key in kinds] for target in manifest.get("target", {}).values(): - sections.extend(target.get(key, {}) for key in ("dependencies", "build-dependencies")) + sections.extend((key, target.get(key, {})) for key in kinds) found = [] - for section in sections: + for kind, section in sections: for alias, specification in section.items(): dependency = specification.get("package", alias) if isinstance(specification, dict) else alias + found.extend(layer_violations(name, dependency, kind)) + if LAYER[name] == CORE and dependency == "rusqlite": + found.append((1, f"rusqlite dependency in core crate {name}")) + if kind == "dev-dependencies": + continue if name in DOMAIN_CRATES and dependency in { "rusqlite", "postgres", @@ -238,9 +318,8 @@ def unsafe_violations(path, source): return found relative = Path(*path.parts[path.parts.index("src") :]) code = "\n".join(line.split("//", 1)[0] for line in source.splitlines()) - if UNSAFE.search(code): - if crate in UNSAFE_FREE_CRATES or str(relative) != UNSAFE_AUDITED_MODULE[crate]: - found.append((1, "unsafe outside the audited module boundary; see core/AGENTS.md")) + if UNSAFE.search(code) and (crate in UNSAFE_FREE_CRATES or str(relative) != UNSAFE_AUDITED_MODULE[crate]): + found.append((1, "unsafe outside the audited module boundary; see core/AGENTS.md")) if relative == Path("src/lib.rs") and UNSAFE_ROOT_ATTR[crate] not in source: found.append((1, f"crate root must declare {UNSAFE_ROOT_ATTR[crate]}")) return found @@ -310,7 +389,9 @@ def overlay_terminology_violations(path, source): def production_files(core, include_sdk=True): """Known product inputs; tests/examples/tools are deliberately outside this scope.""" files = set() - for package in (core / "crates").glob("*"): + for package in crate_directories(core): + if not include_sdk and package == core.parent / "api/binding": + continue if not package.is_dir(): continue files.update(path for path in (package / "src").rglob("*") if path.is_file() and path.suffix in (".rs", ".sql")) @@ -318,7 +399,6 @@ def production_files(core, include_sdk=True): if not include_sdk: return sorted(files) api = core.parent / "api" - files.update((api / "binding" / "src").rglob("*.rs")) for directory in ( api / "agent" / "sdk" / "src", api / "agent" / "cli" / "src", @@ -342,11 +422,17 @@ def main(): if (core / "crates" / name).exists(): print(f"crates/{name}: {RETIRED_PACKAGE}") failures += 1 - manifests = set((core / "crates").glob("*/Cargo.toml")) + manifests = {root / "Cargo.toml" for root in crate_directories(core) if (root / "Cargo.toml").is_file()} + packages = {manifest.parent: tomllib.loads(manifest.read_text())["package"]["name"] for manifest in manifests} for manifest in sorted(manifests): for line, reason in dependency_violations(manifest.read_text()): - print(f"{manifest.relative_to(core)}:{line}: {reason}") + print(f"{manifest.relative_to(core.parent)}:{line}: {reason}") failures += 1 + for package in packages: + for path in sorted((package / "tests").rglob("*.rs")): + for line, reason in test_path_violations(path, path.read_text(), packages): + print(f"{path.relative_to(core.parent)}:{line}: {reason}") + failures += 1 if failures: print(f"FAIL: {failures} product-source boundary violations") return 1 diff --git a/core/tools/test_check_product_boundary.py b/core/tools/test_check_product_boundary.py index 7130c7ed3..f2f66f8ff 100644 --- a/core/tools/test_check_product_boundary.py +++ b/core/tools/test_check_product_boundary.py @@ -1,11 +1,13 @@ +import os +import unittest from pathlib import Path from tempfile import TemporaryDirectory -import unittest from check_product_boundary import ( RETIRED_PACKAGES, dependency_violations, production_files, + test_path_violations, unsafe_violations, violations, ) @@ -221,7 +223,11 @@ def test_cluster1_dependency_edges(self): source = f'[package]\nname="{package}"\n[{table}]\nrenamed={{package="{dependency}",path="../{dependency}"}}\n' self.assertTrue(dependency_violations(source)) source = f'[package]\nname="{package}"\n[dev-dependencies]\n"{dependency}"={{path="../{dependency}"}}\n' - self.assertFalse(dependency_violations(source)) + # Dev edges now obey layers too; project -> workspace stays within engine. + self.assertEqual( + bool(dependency_violations(source)), + not (package == "layerfs-project" and dependency == "layerfs-workspace"), + ) self.assertFalse( dependency_violations( '[package]\nname="layerfs-persistence"\n[dependencies]\nlayerfs-history={path="../layerfs-history"}\n' @@ -398,8 +404,77 @@ def test_skip_sdk_leaves_only_the_sdk_out(self): ) -if __name__ == "__main__": - unittest.main() +class LayerBoundaryTests(unittest.TestCase): + def test_unknown_crate_requires_a_layer(self): + self.assertTrue(dependency_violations('[package]\nname="layerfs-new"')) + self.assertFalse(dependency_violations('[package]\nname="layerfs-content"')) + + def test_production_and_build_edges_obey_layers(self): + for table in ("dependencies", "build-dependencies", "target.'cfg(unix)'.dependencies"): + for dependency, upward in (("layerfs-telemetry", False), ("layerfs-api", True)): + source = f'[package]\nname="layerfs-content"\n[{table}]\nrenamed={{package="{dependency}"}}' + self.assertEqual(bool(dependency_violations(source)), upward) + if upward: + self.assertTrue(any("upward" in reason for _, reason in dependency_violations(source))) + + def test_dev_edges_and_temporary_daemon_exception(self): + for table in ("dev-dependencies", "target.'cfg(unix)'.dev-dependencies"): + for name, dependency, upward in ( + ("layerfs-content", "layerfs-storage", False), + ("layerfs-content", "layerfs-project", True), + ("layerfs-project", "layerfs-workspace", False), + ("layerfs-daemon", "layerfs-api", False), + ("layerfs-workspace", "layerfs-api", True), + ("layerfs-node", "layerfs-api", False), + ): + with self.subTest(table=table, name=name, dependency=dependency): + source = f'[package]\nname="{name}"\n[{table}]\nrenamed={{package="{dependency}"}}' + self.assertEqual(bool(dependency_violations(source)), upward) + + def test_core_rejects_sqlite_in_every_dependency_kind(self): + for table in ("dependencies", "build-dependencies", "dev-dependencies", "target.'cfg(unix)'.dev-dependencies"): + for name in ("layerfs-content", "layerfs-history", "layerfs-storage", "layerfs-telemetry"): + source = f'[package]\nname="{name}"\n[{table}]\ndb={{package="rusqlite",version="1"}}' + self.assertTrue( + any("rusqlite dependency in core" in reason for _, reason in dependency_violations(source)) + ) + self.assertFalse( + dependency_violations('[package]\nname="layerfs-persistence"\n[dev-dependencies]\nrusqlite="1"') + ) + + def test_path_escape_and_narrow_exception(self): + with TemporaryDirectory() as directory: + core = Path(directory) / "core" + packages = { + core / "crates" / name: name + for name in ( + "layerfs-content", + "layerfs-storage", + "layerfs-daemon", + "layerfs-api", + ) + } + content, storage, daemon, api = packages + cases = ( + (content / "tests/read.rs", storage / "tests/helper.rs", False), + (content / "tests/read.rs", api / "tests/helper.rs", True), + (daemon / "tests/merge_report.rs", api / "tests/support/sdk.rs", False), + (daemon / "tests/concurrent_commits.rs", api / "tests/support/installed_store.rs", False), + (daemon / "tests/lane_merge.rs", api / "tests/support/sdk.rs", False), + (daemon / "tests/other.rs", api / "tests/support/sdk.rs", True), + (daemon / "tests/merge_report.rs", api / "tests/other.rs", True), + ) + for path, target, upward in cases: + source = f'#[path = "{os.path.relpath(target, path.parent)}"]\nmod helper;' + with self.subTest(path=path, target=target): + self.assertEqual(bool(test_path_violations(path, source, packages)), upward) + # Resolve dot segments and symlinks before finding the destination owner. + api.mkdir(parents=True) + alias = core / "alias" + alias.symlink_to(api, target_is_directory=True) + path = content / "tests/read.rs" + source = f'#[path = "{alias}/tests/helper.rs"] mod helper;' + self.assertTrue(test_path_violations(path, source, packages)) class DurablePersistenceEdges(unittest.TestCase): @@ -414,3 +489,7 @@ def test_persistence_adapter_accepts_its_domain_edges(self): '[package]\nname="layerfs-persistence"\n[dependencies]\nlayerfs-storage={path="../layerfs-storage"}\nlayerfs-history={path="../layerfs-history"}\n' ) ) + + +if __name__ == "__main__": + unittest.main() From 0f442d5bb729da51d80ee4caaf6da5e505229bcc Mon Sep 17 00:00:00 2001 From: YifanXu1999 Date: Tue, 27 Oct 2026 02:18:55 +0800 Subject: [PATCH 03/10] refactor(463): move Store Init composition into Project Move the unchanged Init and install bodies into layerfs-project::store, retain API re-exports, and call Project Init directly from the native binding. Approve only the owner-selected Project bridge/persistence edges in the layer guard. Checks: all fifteen packages all-target no-run build and Clippy -D warnings; full boundary and fuser guards; 64 Python tool tests; fmt and Ruff format; literal native build, paired Linux SDK build and sealed SDK Init refusal proof. 234 executable runs passed and 112 reuse completed unaffected proofs. Verification exception explicitly authorized by owner: fp21_detach_stages retains two FAILs on the unchanged warmed-reader/provider-gate assumption. Failure output, original container, scratch and execution plan retained; no assertion weakened and no rerun. No unrun executable selections remain. No tests deleted or moved in this step. Production LOC: 102158 -> 102162 (delta +4) Scope: all first-party product implementation, including shipped SQL and JavaScript. before: api 5370, core 96788. after: api 5368, core 96794. Method: tools/production_loc.py --json; exact parent and staged trees; inline tests/comments excluded; shipped SQL and JS included. Counter SHA256: 7e0c3c1ab2fd52895b484c56d18b907cc33b5adbe9a89f8eca77a21ad82b45f0. reference absent (retired R9c; last counted 65,417 at tree 498dd1917812). --- api/binding/Cargo.toml | 1 + api/binding/src/project.rs | 6 +- core/Cargo.lock | 2 + core/README.md | 5 +- core/crates/layerfs-api/src/base/control.rs | 2 +- core/crates/layerfs-api/src/base/internal.rs | 2 +- core/crates/layerfs-api/src/base/mod.rs | 2 - core/crates/layerfs-api/src/lib.rs | 4 +- core/crates/layerfs-api/src/project/mod.rs | 8 +- core/crates/layerfs-project/Cargo.toml | 6 +- core/crates/layerfs-project/src/lib.rs | 3 +- .../src/store}/init.rs | 1 + .../src/store}/install.rs | 2 +- .../src/store}/install_types.rs | 0 core/crates/layerfs-project/src/store/mod.rs | 7 + core/docs/architecture/82-sdk-call-channel.md | 18 ++ core/docs/issues/463/IMPLEMENTATION.md | 165 ++++++++++++++++++ core/tools/check_product_boundary.py | 15 +- core/tools/ci_tests.py | 5 +- core/tools/test_check_product_boundary.py | 14 +- docs/general/sdk.md | 4 +- 21 files changed, 247 insertions(+), 25 deletions(-) rename core/crates/{layerfs-api/src/project => layerfs-project/src/store}/init.rs (99%) rename core/crates/{layerfs-api/src/base => layerfs-project/src/store}/install.rs (98%) rename core/crates/{layerfs-api/src/base => layerfs-project/src/store}/install_types.rs (100%) create mode 100644 core/crates/layerfs-project/src/store/mod.rs create mode 100644 core/docs/issues/463/IMPLEMENTATION.md diff --git a/api/binding/Cargo.toml b/api/binding/Cargo.toml index 5d0521007..b24ba4df1 100644 --- a/api/binding/Cargo.toml +++ b/api/binding/Cargo.toml @@ -13,6 +13,7 @@ crate-type = ["cdylib"] path = "src/lib.rs" [dependencies] +layerfs-project = { path = "../../core/crates/layerfs-project" } layerfs-api = { path = "../../core/crates/layerfs-api" } layerfs-bridge = { path = "../../core/crates/layerfs-bridge" } layerfs-history = { path = "../../core/crates/layerfs-history" } diff --git a/api/binding/src/project.rs b/api/binding/src/project.rs index 0fbee7620..bcfeec94d 100644 --- a/api/binding/src/project.rs +++ b/api/binding/src/project.rs @@ -14,14 +14,12 @@ //! Layers. use crate::job::{failed, refused, Outcome}; use crate::registry::{lock, random, text, Project, INITS}; -use layerfs_api::{ - InitCounters, InitError, InitFailure, InitRequest, InitStep, ProjectApi, ProjectError, - SourceRefusal, -}; use layerfs_bridge::control::{SdkRefusal, SdkValue}; use layerfs_bridge::sdk_values::hex; use layerfs_history::{BranchId, HistoryCatalogConfig, HistoryName, LayerStackId}; use layerfs_persistence::{PersistenceConfig, SqlitePersistenceProfile}; +use layerfs_project::store::{InitError, InitFailure, InitRequest, ProjectApi}; +use layerfs_project::{InitCounters, InitStep, ProjectError, SourceRefusal}; use layerfs_storage::StoragePolicy; use layerfs_telemetry::timer::Timing; use std::path::{Path, PathBuf}; diff --git a/core/Cargo.lock b/core/Cargo.lock index 3bfaf429b..57494bd4f 100644 --- a/core/Cargo.lock +++ b/core/Cargo.lock @@ -626,6 +626,7 @@ dependencies = [ "layerfs-bridge", "layerfs-history", "layerfs-persistence", + "layerfs-project", "layerfs-sandbox", "layerfs-storage", "layerfs-store-service", @@ -661,6 +662,7 @@ dependencies = [ name = "layerfs-project" version = "1.1.0" dependencies = [ + "layerfs-bridge", "layerfs-content", "layerfs-history", "layerfs-persistence", diff --git a/core/README.md b/core/README.md index 43c65d4d1..2e47ec1be 100644 --- a/core/README.md +++ b/core/README.md @@ -14,7 +14,10 @@ under root `crates/` was retired on 2026-10-10 (R9c) and can be read at local ta - **One global Store.** All committed state (content objects, metadata and history) lives in one SQLite Store file, opened with the Disposable profile (WAL, `synchronous=OFF`). Project Init builds and seals it; it is then - installed on a volume the daemons share. + installed on a volume the daemons share. Store Init, sealing and bounded + authenticated install live in `layerfs-project::store`; `layerfs-api` + re-exports their public names. See the + [composition boundary](docs/architecture/82-sdk-call-channel.md#project-store-composition-463). - **Store calls run in the SDK's process.** The JavaScript SDK ([`api`](../api/README.md)) calls `layerfs-api` through the Node binding. Its fs, branch, project and operator methods run on diff --git a/core/crates/layerfs-api/src/base/control.rs b/core/crates/layerfs-api/src/base/control.rs index 22b9cea9f..d981e6143 100644 --- a/core/crates/layerfs-api/src/base/control.rs +++ b/core/crates/layerfs-api/src/base/control.rs @@ -236,7 +236,7 @@ impl Control { fence_error: None, })); } - crate::base::install::install_file(store, manifest, &mut self.connection).inspect_err( + layerfs_project::store::install_file(store, manifest, &mut self.connection).inspect_err( |failure| { if failure.request_attempted { self.failed = true; diff --git a/core/crates/layerfs-api/src/base/internal.rs b/core/crates/layerfs-api/src/base/internal.rs index 2e7678b3a..7bffa705c 100644 --- a/core/crates/layerfs-api/src/base/internal.rs +++ b/core/crates/layerfs-api/src/base/internal.rs @@ -1,12 +1,12 @@ //! Hidden original-channel access for recovery, diagnostics and external proofs. pub use super::control::{Control, ControlCause, ControlFailure, ControlPhase}; -pub use super::install::install; use crate::{BoundWorkspace, OperationFailure, WorkspaceApi}; use layerfs_bridge::{ control::{CleanupObservation, ForcedOutcome, ReadyMount, WorkspaceStatus, WorkspaceToken}, duplex::Connection, }; use layerfs_history::{BranchId, WorkspaceId}; +pub use layerfs_project::store::install; use std::ops::{Deref, DerefMut}; /// Diagnostic facade over the same operation owner, without channel policy changes. diff --git a/core/crates/layerfs-api/src/base/mod.rs b/core/crates/layerfs-api/src/base/mod.rs index 0fdab5cbc..1b7fb4331 100644 --- a/core/crates/layerfs-api/src/base/mod.rs +++ b/core/crates/layerfs-api/src/base/mod.rs @@ -4,8 +4,6 @@ pub(crate) mod args; pub(crate) mod control; pub(crate) mod dispatch; pub(crate) mod failure; -pub(crate) mod install; -pub(crate) mod install_types; #[doc(hidden)] pub mod internal; mod recovery; diff --git a/core/crates/layerfs-api/src/lib.rs b/core/crates/layerfs-api/src/lib.rs index 504a30753..e652d3264 100644 --- a/core/crates/layerfs-api/src/lib.rs +++ b/core/crates/layerfs-api/src/lib.rs @@ -20,11 +20,11 @@ pub mod sandbox; pub use base::dispatch::call; pub use base::failure::{OperationCause, OperationFailure}; pub use base::sdk::{SdkError, SdkResult}; -pub use layerfs_project::{InitCounters, InitCounts, InitStep, ProjectError, SourceRefusal}; -pub use project::{ +pub use layerfs_project::store::{ InitError, InitFailure, InitRequest, InstallError, InstallFailure, InstallWork, Installed, ProjectApi, SealedProject, }; +pub use layerfs_project::{InitCounters, InitCounts, InitStep, ProjectError, SourceRefusal}; #[cfg(unix)] pub use sandbox::{ connect_address, ManagedSandbox, SandboxApi, SandboxCause, SandboxCreate, SandboxFailure, diff --git a/core/crates/layerfs-api/src/project/mod.rs b/core/crates/layerfs-api/src/project/mod.rs index aa81e9ac5..caec551ff 100644 --- a/core/crates/layerfs-api/src/project/mod.rs +++ b/core/crates/layerfs-api/src/project/mod.rs @@ -1,7 +1,7 @@ //! Public Project organization over host Init, and the project's Branches. -pub(crate) mod init; mod list_branches; -pub use crate::base::install_types::{InstallError, InstallFailure, InstallWork, Installed}; -pub use init::ProjectApi; -pub use init::{InitError, InitFailure, InitRequest, SealedProject}; +pub use layerfs_project::store::{ + InitError, InitFailure, InitRequest, InstallError, InstallFailure, InstallWork, Installed, + ProjectApi, SealedProject, +}; pub use list_branches::list_branches; diff --git a/core/crates/layerfs-project/Cargo.toml b/core/crates/layerfs-project/Cargo.toml index 36cc2a5fc..57f132685 100644 --- a/core/crates/layerfs-project/Cargo.toml +++ b/core/crates/layerfs-project/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "layerfs-project" -description = "Engine-independent namespace initialization over C1/C2/C5." +description = "Namespace construction and Store Init/seal/install composition." version.workspace = true edition.workspace = true rust-version.workspace = true @@ -12,6 +12,8 @@ layerfs-storage = { path = "../layerfs-storage" } layerfs-history = { path = "../layerfs-history", default-features = false } layerfs-telemetry = { path = "../layerfs-telemetry" } -[dev-dependencies] layerfs-persistence = { path = "../layerfs-persistence" } +layerfs-bridge = { path = "../layerfs-bridge" } + +[dev-dependencies] sha2 = "=0.11.0" diff --git a/core/crates/layerfs-project/src/lib.rs b/core/crates/layerfs-project/src/lib.rs index d80033f92..0e93b61b2 100644 --- a/core/crates/layerfs-project/src/lib.rs +++ b/core/crates/layerfs-project/src/lib.rs @@ -1,7 +1,8 @@ -//! Namespace Init over the content, storage and history contracts. +//! Namespace construction and Store Init/seal/install composition. #![forbid(unsafe_code)] #![deny(missing_docs)] mod import; +pub mod store; pub use error::{ProjectError, ProjectResult, RetainedAcquisition, SourceRefusal}; #[cfg(unix)] pub(crate) use import::backing; diff --git a/core/crates/layerfs-api/src/project/init.rs b/core/crates/layerfs-project/src/store/init.rs similarity index 99% rename from core/crates/layerfs-api/src/project/init.rs rename to core/crates/layerfs-project/src/store/init.rs index 3411ccc3f..e1cddd2ae 100644 --- a/core/crates/layerfs-api/src/project/init.rs +++ b/core/crates/layerfs-project/src/store/init.rs @@ -1,4 +1,5 @@ //! Host Init and original handoff/failure custody. +use crate as layerfs_project; use layerfs_bridge::provision::{check_destination, ProviderKind, StoreManifest, StoreProfile}; use layerfs_history::{ BranchId, BranchSnapshot, ForkRequest, ForkSource, HistoryCatalog, HistoryCatalogConfig, diff --git a/core/crates/layerfs-api/src/base/install.rs b/core/crates/layerfs-project/src/store/install.rs similarity index 98% rename from core/crates/layerfs-api/src/base/install.rs rename to core/crates/layerfs-project/src/store/install.rs index 3a1760acd..fe8f02d8a 100644 --- a/core/crates/layerfs-api/src/base/install.rs +++ b/core/crates/layerfs-project/src/store/install.rs @@ -1,5 +1,5 @@ //! Bounded one-attempt file streaming; the host never opens the installed Store. -use crate::{InstallError, InstallFailure, InstallWork, Installed, SealedProject}; +use super::{InstallError, InstallFailure, InstallWork, Installed, SealedProject}; use layerfs_bridge::{ control::{ControlError, InstallPhase, InstallReply, INSTALL_FINISH}, duplex::{Connection, MAX_PLAINTEXT_BYTES}, diff --git a/core/crates/layerfs-api/src/base/install_types.rs b/core/crates/layerfs-project/src/store/install_types.rs similarity index 100% rename from core/crates/layerfs-api/src/base/install_types.rs rename to core/crates/layerfs-project/src/store/install_types.rs diff --git a/core/crates/layerfs-project/src/store/mod.rs b/core/crates/layerfs-project/src/store/mod.rs new file mode 100644 index 000000000..2220284a8 --- /dev/null +++ b/core/crates/layerfs-project/src/store/mod.rs @@ -0,0 +1,7 @@ +//! Store Init, sealing and one-attempt installation over the shared libraries. +mod init; +mod install; +mod install_types; +pub use init::{InitError, InitFailure, InitRequest, ProjectApi, SealedProject}; +pub use install::{install, install_file}; +pub use install_types::{InstallError, InstallFailure, InstallWork, Installed}; diff --git a/core/docs/architecture/82-sdk-call-channel.md b/core/docs/architecture/82-sdk-call-channel.md index e15f06849..949b91939 100644 --- a/core/docs/architecture/82-sdk-call-channel.md +++ b/core/docs/architecture/82-sdk-call-channel.md @@ -286,3 +286,21 @@ mounting into a chosen Sandbox (agent), and `backend.daemon.sandbox.get_log`, which reads a Sandbox's daemon log once through the Engine where the binding runs. See the [backend guide](../../../api/how-to-use/backend.md#a-sandboxs-log). + +## Project Store composition (#463) + +Store Init, sealing and bounded authenticated installation live in +[`layerfs-project::store`](../../crates/layerfs-project/src/store/mod.rs). +The existing namespace constructor remains `layerfs_project::init_observed`; +[`store/init.rs`](../../crates/layerfs-project/src/store/init.rs) composes it +with Persistence creation, the first Branch, Init statistics and sole-owner +seal. It requires Disposable explicitly and preserves original failure custody. +Project depends on Bridge for the existing provisioning records and channel +install protocol; it defines no second format or protocol. + +[`layerfs-api::project`](../../crates/layerfs-api/src/project/mod.rs) and its +root retain the existing public names as re-exports. Its Control owner calls +Project's `install_file` without changing correlation or quarantine. The +[Node binding](../../../api/binding/src/project.rs) calls Project's Init once +directly. This is ownership relocation only; no canonical identity, Store +format, behavior or performance claim changes. diff --git a/core/docs/issues/463/IMPLEMENTATION.md b/core/docs/issues/463/IMPLEMENTATION.md new file mode 100644 index 000000000..634519d1d --- /dev/null +++ b/core/docs/issues/463/IMPLEMENTATION.md @@ -0,0 +1,165 @@ +# #463 implementation record + +> **Status:** In progress; source/check record for the layer split. Not a release +> contract or performance qualification. Steps 3 and 4 have not started. + +## Owner decisions + +The owner instructed proceeding with [the migration spec](MIGRATION_SPEC.md) +(G1). In this task's conversation the owner then selected: “Allow project → +bridge; name it engine; relocate now once branch conflicts are resolved.” +This records G2 (Project may use Bridge provisioning types), G3 (`engine`) and +G4 (relocate after branch conflicts are resolved). No push, PR or merge is +requested. Work is isolated on `issue463-layer-split`, from local main +`c137267f59`, with registered private Cargo resources. + +## Prerequisite — binding test placement + +The unmodified parent boundary guard failed on four existing test-only +attributes in `api/binding/src/discovery.rs`, `pool.rs` and `sandbox.rs`. +The owner explicitly selected fixing their placement in a separate prerequisite +commit. Commit `05db985693` removes the private test wiring and exercises the +ordinary built addon through Node's exported methods instead. + +Removed test locations, with all eight behaviors covered at their new homes: + +- `discovery.rs::tests::a_dropped_guard_releases_the_lock_while_a_forked_child_holds_a_copy` + → [native_discovery.rs](../../../../api/binding/tests/native_discovery.rs). +- `tests/unit/admission.rs` (two tests: initial admission and deadline Busy) + → [native_admission.rs](../../../../api/binding/tests/native_admission.rs). +- `tests/unit/reclaim.rs` (five tests: gone-container cleanup, unrelated 404 + custody, replacement-number custody, stopped-container deletion, failed + deletion custody) → `native_discovery.rs` above. + +The lock regression uses a bounded test-only preload fixture to fork while the +actual binding owns the lock. The child retains its open file description while +a later exported binding call acquires the released lock. The admission deadline +proof pays the full public 60-second wait; no private shorter wait or test-only +product API is introduced. [The test guide](../../../../api/binding/tests/README.md) +describes the requirements. JavaScript API test targets remain outside CI under +the owner's existing exclusion. + +Checks passed: Linux Node addon build; test compilation; six native discovery +tests in 0.61 s (30 s ceiling); two native admission tests in 60.52 s (90 s +ceiling); Node all-target warning-denying Clippy; workspace Rust formatting; +full product boundary guard; 63 Python tool tests (120 s ceiling); changed +Python files formatted with Ruff 0.17.2; whitespace check. These fixtures open no +Store. The registered Linux target received Node 24 from the pinned runtime +image for the external calls. + +Production LOC: 102158 -> 102158 (delta 0). +Core 96788; API 5370; all other live product scopes absent. The two-line +reduction from the spec's 102160 snapshot predates this work (merged #436). + +## Step 1 — layer guard + +Commit `2775b3fa44` maps all fifteen Rust crates, including `layerfs-node`, to +layers. It checks production/build/dev edges (including target tables and +aliases), resolved test includes and core rusqlite dependencies. Unknown crates +fail closed. The exact production allowlist and `DOMAIN_CRATES` remain in place. + +The temporary exception is daemon → API, for its dev-dependency and exactly the +six includes from `merge_report`, `concurrent_commits` and `lane_merge` to the +two named API helpers. Step 2b must remove it. + +Checks passed: full guard (953 product inputs), 63 Python tool tests under a +120 s ceiling, Ruff 0.17.2 format/check for the guard and its tests, whitespace. +Rust/runtime checks do not apply to this tooling-only step. No tests deleted. + +Production LOC: 102158 -> 102158 (delta 0), same subtotals as the prerequisite. + +## Step 2a — Project Store composition + +The three implementation files move to +[`layerfs-project::store`](../../../crates/layerfs-project/src/store/mod.rs). +Their bodies remain unchanged. Project gains the approved Bridge and +Persistence production edges; the Node binding calls this Project Init directly. +`layerfs-api` retains its public names as re-exports and its Control owner calls +Project's install operation. Namespace Init retains its existing public API. +Project leaves `DOMAIN_CRATES`; the exact first-party allowlist and direct +third-party database-driver refusal remain enforced. + +Existing API Init and local-install tests still drive Init through the API, so +they stay in API as the spec requires. No tests are deleted in this step. +The full all-target test/example build and warning-denying Clippy passed for +all fifteen packages. Source comparison confirms that the moved files differ +only by the declared imports. The full guard, 64 Python tool tests, Rust +formatting, Ruff formatting and new local documentation links passed. + +Content, Telemetry and Storage package tests passed under individual 100-second +execution ceilings. An additional package-specific compile was interrupted +before any Persistence test ran, after observing redundant feature-unification +rebuilds; its receipt is retained. The run then selected the exact executable +identities from the successful full-workspace build, in fresh Linux containers +with private ext4 scratch, 100-second execution ceilings, and FUSE capabilities +where required. Project and API targets passed. + +Verification stopped on `layerfs-daemon::fp21_detach_stages`: both OPEN and +READDIR cases failed their five-second internal observation of a request held +inside its provider read. The binary returned failure in 10.14 s; it did not +reach the command ceiling. The final execution plan records 234 passed executable runs, one failed run, +112 selections reusing completed Content/Telemetry/Storage and unaffected native +binding proofs, and no unrun selections. + +The test and all of its runtime/fixture code are byte-unchanged by this step. +Its fixture calls namespace Init directly, not the moved Store Init route. +`Store::new(cache_bytes=0)` disables only the shared canonical cache, while +`ReadSession::cached` separately retains up to 3 MiB of pack bodies, decoded +groups and values per Workspace reader. The fixture warms that reader before +arming its provider gate. Those caches can prevent the assumed provider call; +this is the source-based explanation, without a rerun or a product change. +The failed container, scratch volume, original output and execution plan are +retained. The owner explicitly authorized: “Preserve the FP-21 failure and +continue with an explicit verification exception.” The original result remains +FAIL; the test is neither weakened nor rerun. All remaining selections subsequently passed. The literal Node native build, +paired Linux SDK bundle build and sealed SDK `init_refusals.mjs` proof also +passed (the latter under a 90-second ceiling). + +Production LOC: 102158 -> 102162 (delta +4). Core 96794; API 5368, +using the existing physical scopes before relocation. + + +## Relocation coordination + +All five branches named in the spec still have unmerged `core/crates` changes: +`issue442-fs-mode`, `fix/merge-lost-link-count`, `fix/merge-replaced-directory`, +`pr424-log-cap` and `claude/amazing-borg-cc92de`. The first three have open PRs +#445, #418 and #419; #424 remains open under its remote fix branch. The local +Claude worktree also remains registered. No branch is rebased or edited by this +task. After this inventory was reported, the owner confirmed: “Their owners are +ready to rebase; relocate now.” Step 3 is authorized after step 2 verification; +these branches will need rebasing, and this task does not edit them. + +A fresh read of all open PR file lists also finds `core/crates` edits in: + +- #402: `feat/sandbox-local-backend`. +- #403: `macos`. +- #415: `issue379-capacity-guard`. +- #418: `fix/merge-lost-link-count`. +- #419: `fix/merge-replaced-directory`. +- #424: `fix/issue-423-sandbox-log-cap`. +- #427: `feat/macos-native-on-main`. +- #435: `fix/write-through-non-directory`. +- #441: `fix/reclaim-busy-retry`. +- #445: `issue442-fs-mode`. +- #448: `fix/stat-symlink-size`. +- #452: `windows-native-store`. +- #459: `codex/docker-api-diagnostics`. + +Those remote branches will also encounter the path move on their next rebase. +This is coordination inventory only; their work is not edited or merged here. + +## Counting and retained evidence + +Each LOC comparison uses the unchanged root `tools/production_loc.py --json` +from exact parent/staged snapshots, excluding comments and inline tests and +including shipped SQL and the JavaScript API. Staged tree hashes are checked +against the resulting committed trees. Counts are source-size comparisons only. + +reference absent (retired R9c; last counted 65,417 at tree 498dd1917812). + +Build/test logs and exact LOC receipts are retained under the registration's +`builds/` and `artifacts/` directories outside Git. No benchmark is run. +Durable execution is NOT_RUN — disabled by the owner until explicit +reauthorization. No caches have yet been released; active private targets remain +warm until handoff. diff --git a/core/tools/check_product_boundary.py b/core/tools/check_product_boundary.py index 3f1b2b047..6a096cbe0 100644 --- a/core/tools/check_product_boundary.py +++ b/core/tools/check_product_boundary.py @@ -58,6 +58,7 @@ # checked separately. The combined SQLite adapter is the active provider. ALLOWED_DEPENDENCIES = { "layerfs-node": { + "layerfs-project", "layerfs-api", "layerfs-bridge", "layerfs-history", @@ -72,7 +73,14 @@ "layerfs-storage": {"layerfs-content", "layerfs-telemetry"}, "layerfs-history": {"layerfs-content"}, "layerfs-persistence": {"layerfs-storage", "layerfs-history", "layerfs-content", "layerfs-telemetry"}, - "layerfs-project": {"layerfs-content", "layerfs-storage", "layerfs-history", "layerfs-telemetry"}, + "layerfs-project": { + "layerfs-content", + "layerfs-storage", + "layerfs-history", + "layerfs-telemetry", + "layerfs-persistence", + "layerfs-bridge", + }, "layerfs-overlay": set(), "layerfs-workspace": {"layerfs-content", "layerfs-overlay", "layerfs-telemetry"}, "layerfs-fuse": {"layerfs-content", "layerfs-overlay", "layerfs-workspace"}, @@ -116,7 +124,7 @@ "layerfs-bridge": {"layerfs-content", "layerfs-history"}, "layerfs-sandbox": set(), } -DOMAIN_CRATES = {"layerfs-content", "layerfs-storage", "layerfs-history", "layerfs-project"} +DOMAIN_CRATES = {"layerfs-content", "layerfs-storage", "layerfs-history"} LAYER_ORDER = ("core", "engine", "api") CORE, ENGINE, API = LAYER_ORDER LAYER = { @@ -235,7 +243,8 @@ def dependency_violations(source): found.append((1, f"rusqlite dependency in core crate {name}")) if kind == "dev-dependencies": continue - if name in DOMAIN_CRATES and dependency in { + # Project composes Store setup through Persistence, never a database driver. + if name in DOMAIN_CRATES | {"layerfs-project"} and dependency in { "rusqlite", "postgres", "tokio-postgres", diff --git a/core/tools/ci_tests.py b/core/tools/ci_tests.py index fb70b673c..0c77b5659 100644 --- a/core/tools/ci_tests.py +++ b/core/tools/ci_tests.py @@ -39,6 +39,8 @@ # (package, test target): run seconds on the macOS host, 2026-10-23. SLOW = { + # Linux native binding proof, owner-excluded from CI; run explicitly. + ("layerfs-node", "native_admission"): 60.52, ("layerfs-api", "scale_lineage_cap"): 24.3, ("layerfs-api", "sdk_merge_scale"): 23.8, ("layerfs-daemon", "complete_installed_roots"): 9.0, @@ -71,7 +73,8 @@ ("layerfs-content", "filesystem_sorted_localized"): 5.0, } -NIGHTLY = set(SLOW) | set(HEAVY) +# SDK timings are recorded above without adding the owner-excluded API to CI. +NIGHTLY = {target for target in set(SLOW) | set(HEAVY) if target[0] != "layerfs-node"} def metadata(): diff --git a/core/tools/test_check_product_boundary.py b/core/tools/test_check_product_boundary.py index f2f66f8ff..9a6f3e149 100644 --- a/core/tools/test_check_product_boundary.py +++ b/core/tools/test_check_product_boundary.py @@ -260,7 +260,7 @@ def test_project_sqlite_backing_uses_the_owning_provider_boundary(self): self.assertIn("layerfs-persistence", findings[0][1]) def test_domain_source_component_names(self): - for folder in ("layerfs-storage", "layerfs-history", "layerfs-project", "layerfs-content"): + for folder in ("layerfs-storage", "layerfs-history", "layerfs-content"): path = Path("core/crates") / folder / "src" / "implementation.rs" self.assertTrue(violations(path, "use layerfs_s3::S3Objects;")) self.assertTrue(violations(path, "// layerfs-metadata owns this")) @@ -269,6 +269,18 @@ def test_domain_source_component_names(self): self.assertFalse(violations(path, "use layerfs_storage::port::MetadataStore;")) self.assertTrue(violations(path, "use layerfs_s3::S3Objects;")) + def test_project_store_composition_uses_approved_engine_edges(self): + path = Path("core/crates/layerfs-project/src/store/init.rs") + for dependency in ("layerfs-persistence", "layerfs-bridge"): + self.assertFalse(violations(path, f"use {dependency.replace('-', '_')}::PublicType;")) + self.assertFalse( + dependency_violations( + f'[package]\nname="layerfs-project"\n[dependencies]\n{dependency}={{path="../{dependency}"}}' + ) + ) + self.assertTrue(violations(path, "use layerfs_api::ProjectApi;")) + self.assertTrue(violations(path, "use layerfs_workspace::Workspace;")) + def test_storage_encoding_engine_boundary(self): for folder in ("encoding", "pack"): path = Path("core/crates/layerfs-storage/src") / folder / "read.rs" diff --git a/docs/general/sdk.md b/docs/general/sdk.md index e259df629..6431d7f25 100644 --- a/docs/general/sdk.md +++ b/docs/general/sdk.md @@ -55,7 +55,9 @@ correlation, retries a failure or silently cleans up an uncertain resource. ## Project -[Init](../../core/crates/layerfs-api/src/project/init.rs) imports the complete native +[Init](../../core/crates/layerfs-project/src/store/init.rs) lives in +`layerfs-project::store`, re-exported by `layerfs-api`. The Node binding calls +that same Project implementation directly. Init imports the complete native tree, including Git metadata, ignored files, dependencies, symlinks, caches and output. It retains the original eleven-field InitRequest and caller timer: source, Store configuration, daemon locator, storage policy, catalog authority, stack and From 3cae8b1a1e4ac9544b28d05ac2b3b39a6741ddd9 Mon Sep 17 00:00:00 2001 From: YifanXu1999 Date: Tue, 27 Oct 2026 02:33:10 +0800 Subject: [PATCH 04/10] refactor(463): move SDK-facing daemon tests into API Move mount_control, kernel_mount_routes, kernel_application, observed_application, r5_1_actual_daemon_commit, merge_report, concurrent_commits and lane_merge to layerfs-api/tests. Keep their assertions and existing lower-layer fixtures; locate the ordinary separately built daemon binary from three API tests. Install-only daemon tests, fixtures and the resource_prepare example now use Project's Store entrypoint directly. Remove daemon's API dev edge and every temporary upward guard exception. API adds daemon, FUSE and the existing pinned nix as test dependencies only. CI selection follows the moved heavy and Linux mount targets. No versions or production behavior change. No tests deleted. Checks: full fifteen-package all-target no-run compilation and Clippy -D warnings; focused Project/API/daemon executable proofs; native binding build; full product and fuser guards; 64 Python self-tests; Rust fmt, Ruff format and whitespace. The unchanged FP-21 failure remains FAIL under the explicit owner exception; its original proof is retained and is not rerun. Unaffected proofs are reused. Production LOC: 102162 -> 102162 (delta +0) Scope: all first-party product implementation, including shipped SQL and JavaScript. before: api 5368, core 96794. after: api 5368, core 96794. Method: tools/production_loc.py --json; exact parent and staged trees; inline tests/comments excluded; shipped SQL and JS included. Counter SHA256: 7e0c3c1ab2fd52895b484c56d18b907cc33b5adbe9a89f8eca77a21ad82b45f0. reference absent (retired R9c; last counted 65,417 at tree 498dd1917812). --- .github/workflows/nightly.yml | 4 +-- core/Cargo.lock | 4 ++- core/crates/layerfs-api/Cargo.toml | 3 ++ .../tests/concurrent_commits.rs | 4 +-- .../tests/kernel_application.rs | 6 ++-- .../tests/kernel_mount_routes.rs | 4 +-- .../tests/lane_merge.rs | 4 +-- .../tests/merge_report.rs | 4 +-- .../tests/mount_control.rs | 6 ++-- .../tests/observed_application.rs | 8 +++-- .../tests/r5_1_actual_daemon_commit.rs | 16 +++++---- .../tests/support/daemon_binary.rs | 21 +++++++++++ core/crates/layerfs-daemon/Cargo.toml | 1 - .../examples/resource_prepare.rs | 2 +- .../layerfs-daemon/tests/host_handoff.rs | 2 +- .../layerfs-daemon/tests/host_install.rs | 10 +++--- .../tests/support/complete_fixture.rs | 4 +-- .../tests/support/control_fixture.rs | 2 +- .../tests/support/host_install.rs | 2 +- core/docs/issues/463/IMPLEMENTATION.md | 35 ++++++++++++++++++- core/tools/check_product_boundary.py | 12 ------- core/tools/ci_tests.py | 16 +++++++-- core/tools/test_check_product_boundary.py | 12 +++---- core/tools/test_ci_tests.py | 8 +++-- 24 files changed, 127 insertions(+), 63 deletions(-) rename core/crates/{layerfs-daemon => layerfs-api}/tests/concurrent_commits.rs (98%) rename core/crates/{layerfs-daemon => layerfs-api}/tests/kernel_application.rs (97%) rename core/crates/{layerfs-daemon => layerfs-api}/tests/kernel_mount_routes.rs (99%) rename core/crates/{layerfs-daemon => layerfs-api}/tests/lane_merge.rs (99%) rename core/crates/{layerfs-daemon => layerfs-api}/tests/merge_report.rs (97%) rename core/crates/{layerfs-daemon => layerfs-api}/tests/mount_control.rs (99%) rename core/crates/{layerfs-daemon => layerfs-api}/tests/observed_application.rs (99%) rename core/crates/{layerfs-daemon => layerfs-api}/tests/r5_1_actual_daemon_commit.rs (97%) create mode 100644 core/crates/layerfs-api/tests/support/daemon_binary.rs diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index c88ef42ea..b7e57daf9 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -3,7 +3,7 @@ # - slow: binaries that take 5 s or more to run, plus the "heavy" ones that # take 5 s or more of build CPU (left out of the push job), on the # runner -# - mount: Linux-only layerfs-daemon targets that mount FUSE. Each binary runs +# - mount: Linux-only daemon and SDK targets that mount FUSE. Each binary runs # in its own fresh container with /dev/fuse and SYS_ADMIN, as the # existing native proofs do: forced_unavailable needs fusectl absent, # and fp2_negotiation_flags needs one test thread. @@ -66,7 +66,7 @@ jobs: run: | targets="$(python3 -B core/tools/ci_tests.py mount-targets)" # shellcheck disable=SC2086 # one --test flag per word - cargo +1.85.1 test --manifest-path core/Cargo.toml --locked -p layerfs-daemon \ + cargo +1.85.1 test --manifest-path core/Cargo.toml --locked -p layerfs-daemon -p layerfs-api \ $targets --no-run --message-format json > "$RUNNER_TEMP/build.json" python3 -B core/tools/ci_tests.py executables < "$RUNNER_TEMP/build.json" > "$RUNNER_TEMP/mount.tsv" test -s "$RUNNER_TEMP/mount.tsv" diff --git a/core/Cargo.lock b/core/Cargo.lock index 57494bd4f..ca39be0e9 100644 --- a/core/Cargo.lock +++ b/core/Cargo.lock @@ -549,6 +549,8 @@ dependencies = [ "blake3", "layerfs-bridge", "layerfs-content", + "layerfs-daemon", + "layerfs-fuse", "layerfs-history", "layerfs-overlay", "layerfs-persistence", @@ -558,6 +560,7 @@ dependencies = [ "layerfs-store-service", "layerfs-telemetry", "layerfs-workspace", + "nix", "rusqlite", ] @@ -583,7 +586,6 @@ name = "layerfs-daemon" version = "1.1.0" dependencies = [ "blake3", - "layerfs-api", "layerfs-bridge", "layerfs-content", "layerfs-fuse", diff --git a/core/crates/layerfs-api/Cargo.toml b/core/crates/layerfs-api/Cargo.toml index ff0c6178d..335755733 100644 --- a/core/crates/layerfs-api/Cargo.toml +++ b/core/crates/layerfs-api/Cargo.toml @@ -18,6 +18,9 @@ layerfs-sandbox = { path = "../layerfs-sandbox" } layerfs-store-service = { path = "../layerfs-store-service" } [dev-dependencies] +nix = { version = "=0.31.3", features = ["fs", "user", "process"] } +layerfs-daemon = { path = "../layerfs-daemon" } +layerfs-fuse = { path = "../layerfs-fuse" } # #364: the write-cost harness times BLAKE3 over the bytes it writes. blake3 = { version = "=1.8.5", default-features = false } # The Store method tests bind private Workspaces and count the Store's rows. diff --git a/core/crates/layerfs-daemon/tests/concurrent_commits.rs b/core/crates/layerfs-api/tests/concurrent_commits.rs similarity index 98% rename from core/crates/layerfs-daemon/tests/concurrent_commits.rs rename to core/crates/layerfs-api/tests/concurrent_commits.rs index a1b61091d..17324b1c4 100644 --- a/core/crates/layerfs-daemon/tests/concurrent_commits.rs +++ b/core/crates/layerfs-api/tests/concurrent_commits.rs @@ -4,10 +4,10 @@ //! start the Commits together and every wait is bounded by the test ceiling. //! Workspace Commits go through the daemon; the SDK calls that set up and read //! back run in-process over the same Store (#352 F-020). -#[path = "../../layerfs-api/tests/support/installed_store.rs"] +#[path = "support/installed_store.rs"] #[allow(dead_code)] mod installed; -#[path = "../../layerfs-api/tests/support/sdk.rs"] +#[path = "support/sdk.rs"] #[allow(dead_code)] mod support; diff --git a/core/crates/layerfs-daemon/tests/kernel_application.rs b/core/crates/layerfs-api/tests/kernel_application.rs similarity index 97% rename from core/crates/layerfs-daemon/tests/kernel_application.rs rename to core/crates/layerfs-api/tests/kernel_application.rs index 7f82804b9..0d9b1c595 100644 --- a/core/crates/layerfs-daemon/tests/kernel_application.rs +++ b/core/crates/layerfs-api/tests/kernel_application.rs @@ -1,7 +1,9 @@ //! Actual Linux daemon binary, protected config and direct Store installation. #![cfg(target_os = "linux")] +#[path = "support/daemon_binary.rs"] +mod daemon_binary; #[allow(dead_code)] -#[path = "support/host_install.rs"] +#[path = "../../layerfs-daemon/tests/support/host_install.rs"] mod support; use layerfs_api::internal::Control; use layerfs_bridge::{ @@ -63,7 +65,7 @@ fn actual_daemon_install_hello_bind_status_no_constructor_and_session_end() { fs::write(&config, setup.encode().unwrap()).unwrap(); fs::set_permissions(&config, fs::Permissions::from_mode(0o600)).unwrap(); let mut child = Process( - Command::new(env!("CARGO_BIN_EXE_layerfs-daemon")) + Command::new(daemon_binary::path()) .arg("--config") .arg(&config) .stdin(Stdio::null()) diff --git a/core/crates/layerfs-daemon/tests/kernel_mount_routes.rs b/core/crates/layerfs-api/tests/kernel_mount_routes.rs similarity index 99% rename from core/crates/layerfs-daemon/tests/kernel_mount_routes.rs rename to core/crates/layerfs-api/tests/kernel_mount_routes.rs index 8082c7a54..cca769069 100644 --- a/core/crates/layerfs-daemon/tests/kernel_mount_routes.rs +++ b/core/crates/layerfs-api/tests/kernel_mount_routes.rs @@ -3,10 +3,10 @@ //! frequent fresh mounts and sustained work on one mount. #![cfg(target_os = "linux")] #[allow(dead_code)] -#[path = "support/mounted.rs"] +#[path = "../../layerfs-daemon/tests/support/mounted.rs"] mod mounted; #[allow(dead_code)] -#[path = "support/host_install.rs"] +#[path = "../../layerfs-daemon/tests/support/host_install.rs"] mod support; use layerfs_api::{internal::Control, OperationCause}; use layerfs_bridge::control::{ diff --git a/core/crates/layerfs-daemon/tests/lane_merge.rs b/core/crates/layerfs-api/tests/lane_merge.rs similarity index 99% rename from core/crates/layerfs-daemon/tests/lane_merge.rs rename to core/crates/layerfs-api/tests/lane_merge.rs index 579ec5eb4..eacf686a4 100644 --- a/core/crates/layerfs-daemon/tests/lane_merge.rs +++ b/core/crates/layerfs-api/tests/lane_merge.rs @@ -7,10 +7,10 @@ //! The Commit under test runs over a Store whose history wrapper holds its //! first `publish_lane` call until the test has landed the other Commit, at //! the public catalog boundary. Every wait is bounded. -#[path = "../../layerfs-api/tests/support/installed_store.rs"] +#[path = "support/installed_store.rs"] #[allow(dead_code)] mod installed; -#[path = "../../layerfs-api/tests/support/sdk.rs"] +#[path = "support/sdk.rs"] #[allow(dead_code)] mod support; diff --git a/core/crates/layerfs-daemon/tests/merge_report.rs b/core/crates/layerfs-api/tests/merge_report.rs similarity index 97% rename from core/crates/layerfs-daemon/tests/merge_report.rs rename to core/crates/layerfs-api/tests/merge_report.rs index 86dfc7d24..5051e1b17 100644 --- a/core/crates/layerfs-daemon/tests/merge_report.rs +++ b/core/crates/layerfs-api/tests/merge_report.rs @@ -2,10 +2,10 @@ //! does not hold (#355 F-041). The merge lists at most 4,096 paths it changed //! in the Workspace; past that the reply says `truncated`, below it the list //! is complete and `truncated` is false. -#[path = "../../layerfs-api/tests/support/installed_store.rs"] +#[path = "support/installed_store.rs"] #[allow(dead_code)] mod installed; -#[path = "../../layerfs-api/tests/support/sdk.rs"] +#[path = "support/sdk.rs"] #[allow(dead_code)] mod support; diff --git a/core/crates/layerfs-daemon/tests/mount_control.rs b/core/crates/layerfs-api/tests/mount_control.rs similarity index 99% rename from core/crates/layerfs-daemon/tests/mount_control.rs rename to core/crates/layerfs-api/tests/mount_control.rs index f0f850be8..fcd075faa 100644 --- a/core/crates/layerfs-daemon/tests/mount_control.rs +++ b/core/crates/layerfs-api/tests/mount_control.rs @@ -1,10 +1,10 @@ //! Authenticated control over an actually installed Store and one real owner. -#[path = "support/control_fixture.rs"] +#[path = "../../layerfs-daemon/tests/support/control_fixture.rs"] mod fixture; -#[path = "support/held_writer.rs"] +#[path = "../../layerfs-daemon/tests/support/held_writer.rs"] mod held_writer; #[allow(dead_code)] -#[path = "support/host_install.rs"] +#[path = "../../layerfs-daemon/tests/support/host_install.rs"] mod support; use layerfs_api::{internal::Control, OperationCause}; use layerfs_bridge::control::{Activity, ControlCode, Reply, Request, WorkspaceToken}; diff --git a/core/crates/layerfs-daemon/tests/observed_application.rs b/core/crates/layerfs-api/tests/observed_application.rs similarity index 99% rename from core/crates/layerfs-daemon/tests/observed_application.rs rename to core/crates/layerfs-api/tests/observed_application.rs index d6f26296a..280904d3e 100644 --- a/core/crates/layerfs-daemon/tests/observed_application.rs +++ b/core/crates/layerfs-api/tests/observed_application.rs @@ -1,7 +1,9 @@ //! Authentic daemon observations preserve ordinary effects and explicit identities. #![cfg(target_os = "linux")] +#[path = "support/daemon_binary.rs"] +mod daemon_binary; #[allow(dead_code)] -#[path = "support/host_install.rs"] +#[path = "../../layerfs-daemon/tests/support/host_install.rs"] mod support; use layerfs_api::internal::Control; #[cfg(target_os = "linux")] @@ -97,7 +99,7 @@ fn start_with( ) -> (Process, SocketAddr, Control, StoreManifest) { let config = configure(f, &deployment); let mut process = Process( - Command::new(env!("CARGO_BIN_EXE_layerfs-daemon")) + Command::new(daemon_binary::path()) .arg("--config") .arg(&config) .stdin(Stdio::null()) @@ -829,7 +831,7 @@ fn startup_refuses_a_serial_low_water_at_or_above_the_refill_window() { ); let log = f.directory.join("refused.log"); let mut process = Process( - Command::new(env!("CARGO_BIN_EXE_layerfs-daemon")) + Command::new(daemon_binary::path()) .arg("--config") .arg(&config) .stdin(Stdio::null()) diff --git a/core/crates/layerfs-daemon/tests/r5_1_actual_daemon_commit.rs b/core/crates/layerfs-api/tests/r5_1_actual_daemon_commit.rs similarity index 97% rename from core/crates/layerfs-daemon/tests/r5_1_actual_daemon_commit.rs rename to core/crates/layerfs-api/tests/r5_1_actual_daemon_commit.rs index 668e49590..be1a43155 100644 --- a/core/crates/layerfs-daemon/tests/r5_1_actual_daemon_commit.rs +++ b/core/crates/layerfs-api/tests/r5_1_actual_daemon_commit.rs @@ -18,20 +18,22 @@ //! "chosen by the clock" (`rig::clock_masked`). Owner, `st_nlink`, `st_size` //! and `st_ino` sharing are checked against the kernel's own table. #![cfg(target_os = "linux")] +#[path = "support/daemon_binary.rs"] +mod daemon_binary; #[allow(dead_code)] -#[path = "support/installed_store.rs"] +#[path = "../../layerfs-daemon/tests/support/installed_store.rs"] mod installed; #[allow(dead_code)] -#[path = "support/namespace_model.rs"] +#[path = "../../layerfs-daemon/tests/support/namespace_model.rs"] mod model; #[allow(dead_code)] -#[path = "support/mounted.rs"] +#[path = "../../layerfs-daemon/tests/support/mounted.rs"] mod mounted; #[allow(dead_code)] -#[path = "support/mounted_commit.rs"] +#[path = "../../layerfs-daemon/tests/support/mounted_commit.rs"] mod rig; #[allow(dead_code)] -#[path = "support/host_install.rs"] +#[path = "../../layerfs-daemon/tests/support/host_install.rs"] mod support; use layerfs_api::internal::Control; use layerfs_bridge::{ @@ -126,7 +128,7 @@ fn start(f: &support::Fixture, mounts: &Path) -> (Process, SocketAddr) { fs::write(&config, setup.encode().unwrap()).unwrap(); fs::set_permissions(&config, fs::Permissions::from_mode(0o600)).unwrap(); let mut process = Process( - Command::new(env!("CARGO_BIN_EXE_layerfs-daemon")) + Command::new(daemon_binary::path()) .arg("--config") .arg(&config) .stdin(Stdio::null()) @@ -301,7 +303,7 @@ fn r5_1_the_actual_daemon_commits_a_change_by_external_bash_and_a_fresh_mount_is let mount = Path::new(&ready.directory); println!( "{name} STARTED executable={} pid={} listen={address} phase={:?} store_sqlite={} mount={} command_identity={COMMAND}:{COMMAND}", - env!("CARGO_BIN_EXE_layerfs-daemon"), + daemon_binary::path().display(), process.0.id(), hello.phase, hello.store_sqlite.as_deref().unwrap(), diff --git a/core/crates/layerfs-api/tests/support/daemon_binary.rs b/core/crates/layerfs-api/tests/support/daemon_binary.rs new file mode 100644 index 000000000..91c7fc0c0 --- /dev/null +++ b/core/crates/layerfs-api/tests/support/daemon_binary.rs @@ -0,0 +1,21 @@ +//! Locate the ordinary daemon binary built alongside these SDK integration tests. +use std::path::PathBuf; + +pub fn path() -> PathBuf { + if let Some(path) = std::env::var_os("LAYERFS_TEST_DAEMON") { + return path.into(); + } + let executable = std::env::current_exe().expect("integration test executable"); + let binary = executable + .parent() + .unwrap() + .parent() + .unwrap() + .join("layerfs-daemon"); + assert!( + binary.is_file(), + "build layerfs-daemon before SDK tests: {}", + binary.display() + ); + binary +} diff --git a/core/crates/layerfs-daemon/Cargo.toml b/core/crates/layerfs-daemon/Cargo.toml index 592a88926..bf16e61e7 100644 --- a/core/crates/layerfs-daemon/Cargo.toml +++ b/core/crates/layerfs-daemon/Cargo.toml @@ -23,5 +23,4 @@ nix = { version = "=0.31.3", features = ["fs", "user", "process"] } [dev-dependencies] blake3 = { version = "=1.8.5", default-features = false } -layerfs-api = { path = "../layerfs-api" } layerfs-project = { path = "../layerfs-project" } diff --git a/core/crates/layerfs-daemon/examples/resource_prepare.rs b/core/crates/layerfs-daemon/examples/resource_prepare.rs index e88634b6b..bf5d34aad 100644 --- a/core/crates/layerfs-daemon/examples/resource_prepare.rs +++ b/core/crates/layerfs-daemon/examples/resource_prepare.rs @@ -1,7 +1,7 @@ //! Separate host-only preparation for the registered growth cases. -use layerfs_api::{InitRequest, ProjectApi}; use layerfs_history::{BranchId, HistoryCatalogConfig, HistoryName, LayerStackId}; use layerfs_persistence::{PersistenceConfig, SqlitePersistenceProfile}; +use layerfs_project::store::{InitRequest, ProjectApi}; use layerfs_storage::StoragePolicy; use layerfs_telemetry::timer::Timing; use std::{ diff --git a/core/crates/layerfs-daemon/tests/host_handoff.rs b/core/crates/layerfs-daemon/tests/host_handoff.rs index 5ec40f044..123b38d08 100644 --- a/core/crates/layerfs-daemon/tests/host_handoff.rs +++ b/core/crates/layerfs-daemon/tests/host_handoff.rs @@ -23,7 +23,7 @@ fn macos_init_handoff_to_linux_daemon_has_no_host_data_path() { duplex::public_key(&support::SERVER_PRIVATE).unwrap(), ) .unwrap(); - let ack = layerfs_api::internal::install(&fixture.project, &mut connection).unwrap(); + let ack = layerfs_project::store::install(&fixture.project, &mut connection).unwrap(); assert_eq!(ack.manifest.host_sqlite, "3.51.0"); assert_eq!(ack.manifest.daemon_sqlite.as_deref(), Some("3.53.2")); assert_eq!(ack.work.sent_bytes, fixture.project.store.bytes); diff --git a/core/crates/layerfs-daemon/tests/host_install.rs b/core/crates/layerfs-daemon/tests/host_install.rs index 880da0817..729733d98 100644 --- a/core/crates/layerfs-daemon/tests/host_install.rs +++ b/core/crates/layerfs-daemon/tests/host_install.rs @@ -15,7 +15,7 @@ fn authenticated_install_opens_one_store_and_reads_the_complete_root() { let (mut client, worker) = support::pair(move |connection| { receive_install(connection, &target, StoreSettings::default()) }); - let ack = layerfs_api::internal::install(&fixture.project, &mut client).unwrap(); + let ack = layerfs_project::store::install(&fixture.project, &mut client).unwrap(); let installed = worker.join().unwrap(); assert_eq!(ack.manifest, installed.manifest); assert_eq!(ack.work.sent_bytes, installed.work.written); @@ -43,9 +43,9 @@ fn existing_store_is_refused_before_upload_and_preserved() { let (mut client, worker) = support::pair(move |connection| { receive_install(connection, &destination, StoreSettings::default()) }); - let failure = layerfs_api::internal::install(&fixture.project, &mut client).unwrap_err(); + let failure = layerfs_project::store::install(&fixture.project, &mut client).unwrap_err(); assert!( - matches!(failure.error,layerfs_api::InstallError::Remote(ref remote) if remote.kind==RefusalKind::Exists && !remote.published && !remote.claim_acknowledged && remote.written==0) + matches!(failure.error,layerfs_project::store::InstallError::Remote(ref remote) if remote.kind==RefusalKind::Exists && !remote.published && !remote.claim_acknowledged && remote.written==0) ); assert!(!failure.accepted); assert_eq!(failure.work.sent_bytes, 0); @@ -77,9 +77,9 @@ fn interrupted_transfer_keeps_original_partial_file_and_claim_refuses_another_in let (mut second, other) = support::pair(move |connection| { receive_install(connection, &target, StoreSettings::default()) }); - let refusal = layerfs_api::internal::install(&fixture.project, &mut second).unwrap_err(); + let refusal = layerfs_project::store::install(&fixture.project, &mut second).unwrap_err(); assert!( - matches!(refusal.error,layerfs_api::InstallError::Remote(ref value) if value.kind==RefusalKind::Exists) + matches!(refusal.error,layerfs_project::store::InstallError::Remote(ref value) if value.kind==RefusalKind::Exists) ); let refused = other.join().err().unwrap(); assert!(!refused.claim_acknowledged && !refused.published); diff --git a/core/crates/layerfs-daemon/tests/support/complete_fixture.rs b/core/crates/layerfs-daemon/tests/support/complete_fixture.rs index 2ee9441bf..6c2deb7ee 100644 --- a/core/crates/layerfs-daemon/tests/support/complete_fixture.rs +++ b/core/crates/layerfs-daemon/tests/support/complete_fixture.rs @@ -1,6 +1,5 @@ //! Kernel source creation and authenticated installation, retaining failures. use super::{bytes, support}; -use layerfs_api::{InitRequest, ProjectApi}; use layerfs_content::filesystem::attributes::PortableMetadata; use layerfs_daemon::{ bootstrap::{open_store_observed, OpenedStore}, @@ -9,6 +8,7 @@ use layerfs_daemon::{ }; use layerfs_history::{BranchId, HistoryCatalogConfig, HistoryName, LayerStackId}; use layerfs_persistence::{PersistenceConfig, SqlitePersistenceProfile}; +use layerfs_project::store::{InitRequest, ProjectApi}; use layerfs_storage::StoragePolicy; use layerfs_telemetry::timer::Timing; use std::{ @@ -245,7 +245,7 @@ impl Fixture { let cache_bytes = settings.cache_bytes; let (mut channel, worker) = support::pair(move |channel| receive_install(channel, &destination, settings)); - let ack = layerfs_api::internal::install(&project, &mut channel).unwrap(); + let ack = layerfs_project::store::install(&project, &mut channel).unwrap(); let installed = worker.join().unwrap(); fs::remove_file(project.store.path).unwrap(); println!( diff --git a/core/crates/layerfs-daemon/tests/support/control_fixture.rs b/core/crates/layerfs-daemon/tests/support/control_fixture.rs index 7934ee39f..b5aa32836 100644 --- a/core/crates/layerfs-daemon/tests/support/control_fixture.rs +++ b/core/crates/layerfs-daemon/tests/support/control_fixture.rs @@ -39,7 +39,7 @@ impl Fixture { let (mut client, worker) = support::pair(move |connection| { receive_install(connection, &target, StoreSettings::default()) }); - layerfs_api::internal::install(&host.project, &mut client).unwrap(); + layerfs_project::store::install(&host.project, &mut client).unwrap(); let installed = worker.join().unwrap(); let owner = Owner::start( &host.directory.join("overlay.sqlite"), diff --git a/core/crates/layerfs-daemon/tests/support/host_install.rs b/core/crates/layerfs-daemon/tests/support/host_install.rs index 5a23d5447..ba400a098 100644 --- a/core/crates/layerfs-daemon/tests/support/host_install.rs +++ b/core/crates/layerfs-daemon/tests/support/host_install.rs @@ -1,9 +1,9 @@ //! External authenticated endpoints and complete small-root installation oracle. -use layerfs_api::{InitRequest, ProjectApi, SealedProject}; use layerfs_bridge::duplex::{self, Connection}; use layerfs_daemon::{install_types::InstalledStore, store::BindRequest, Owner, OwnerConfig}; use layerfs_history::{BranchId, HistoryCatalogConfig, HistoryName, LayerStackId, WorkspaceId}; use layerfs_persistence::{PersistenceConfig, SqlitePersistenceProfile}; +use layerfs_project::store::{InitRequest, ProjectApi, SealedProject}; use layerfs_storage::StoragePolicy; use layerfs_telemetry::timer::Timing; use std::{ diff --git a/core/docs/issues/463/IMPLEMENTATION.md b/core/docs/issues/463/IMPLEMENTATION.md index 634519d1d..cb1ae0f07 100644 --- a/core/docs/issues/463/IMPLEMENTATION.md +++ b/core/docs/issues/463/IMPLEMENTATION.md @@ -70,7 +70,7 @@ Production LOC: 102158 -> 102158 (delta 0), same subtotals as the prerequisite. ## Step 2a — Project Store composition -The three implementation files move to +Commit `0f442d5bb7`: the three implementation files move to [`layerfs-project::store`](../../../crates/layerfs-project/src/store/mod.rs). Their bodies remain unchanged. Project gains the approved Bridge and Persistence production edges; the Node binding calls this Project Init directly. @@ -119,6 +119,39 @@ Production LOC: 102158 -> 102162 (delta +4). Core 96794; API 5368, using the existing physical scopes before relocation. +## Step 2b — daemon test ownership + +Eight test targets move from daemon to API: `mount_control`, +`kernel_mount_routes`, `kernel_application`, `observed_application`, +`r5_1_actual_daemon_commit`, `merge_report`, `concurrent_commits` and +`lane_merge`. Their assertions survive unchanged. The first five keep cheap +path includes into lower-layer daemon fixtures; the last three now include +API's own helpers locally. Three targets locate the separately built ordinary +daemon binary through a small API test helper, since Cargo's binary variable +is package-local. + +Daemon's `host_install` and `host_handoff`, their three shared install/Init +fixtures, and the `resource_prepare` example use Project Store composition +instead of API. API gains daemon/FUSE and the already locked nix test edges; +daemon drops its API dev-dependency. No dependency version changes. No tests +are deleted. The boundary guard removes both temporary upward exceptions, and +its self-tests require daemon → API to fail in every dependency/include case. +CI's mount lane follows the four Linux-only moved targets into API, while +`mount_control` remains in the heavy group at its new home. + +Checks passed: all fifteen packages' all-target no-run compilation and +warning-denying Clippy, literal native addon build, full boundary/fuser guards, +64 Python self-tests, Rust formatting, changed Python Ruff formatting and +whitespace. All 121 focused Project/API/daemon executable selections passed; +225 unaffected selections reuse their existing proofs. The unchanged FP-21 +selection retains its original FAIL under the explicit owner exception, without +a rerun, and no selection remains unrun. The moved `observed_application` +proof took 6.30 s; its SLOW timing is recorded while it stays in the mount lane. + +Production LOC: 102162 -> 102162 (delta 0). Core 96794; API 5368, +using the physical scopes before relocation. + + ## Relocation coordination All five branches named in the spec still have unmerged `core/crates` changes: diff --git a/core/tools/check_product_boundary.py b/core/tools/check_product_boundary.py index 6a096cbe0..7118b9030 100644 --- a/core/tools/check_product_boundary.py +++ b/core/tools/check_product_boundary.py @@ -144,21 +144,12 @@ "layerfs-api": API, "layerfs-node": API, } -# Temporary upward test link; migration #463 step 2b removes both exceptions. -UPWARD_TEST_EDGE = ("layerfs-daemon", "layerfs-api") -UPWARD_TEST_PATHS = { - (f"tests/{test}.rs", f"tests/support/{helper}.rs") - for test in ("merge_report", "concurrent_commits", "lane_merge") - for helper in ("installed_store", "sdk") -} def layer_violations(name, dependency, kind): if dependency.startswith("layerfs-") and dependency not in LAYER: return [(1, f"crate missing from layer map: {dependency}")] if dependency in LAYER and LAYER_ORDER.index(LAYER[dependency]) > LAYER_ORDER.index(LAYER[name]): - if kind == "dev-dependencies" and (name, dependency) == UPWARD_TEST_EDGE: - return [] return [(1, f"upward {kind} edge {name} ({LAYER[name]}) -> {dependency} ({LAYER[dependency]})")] return [] @@ -182,9 +173,6 @@ def test_path_violations(path, source, packages): if destination is None: continue name, dependency = packages[owner], packages[destination] - exception = (path.relative_to(owner).as_posix(), target.relative_to(destination).as_posix()) - if (name, dependency) == UPWARD_TEST_EDGE and exception in UPWARD_TEST_PATHS: - continue for _, reason in layer_violations(name, dependency, "test #[path]"): found.append((source.count("\n", 0, match.start()) + 1, reason)) return found diff --git a/core/tools/ci_tests.py b/core/tools/ci_tests.py index 0c77b5659..27bc1998f 100644 --- a/core/tools/ci_tests.py +++ b/core/tools/ci_tests.py @@ -9,7 +9,7 @@ slow binaries that take 5 s or more to run (macOS host, 2026-10-23) heavy binaries that take 5 s or more of build CPU (moved by the owner, 2026-10-23) - mount layerfs-daemon targets that are Linux-only (`#![cfg(target_os = + mount daemon targets and the SDK mount targets that are Linux-only (`#![cfg(target_os = "linux")]`): they mount FUSE and need /dev/fuse, SYS_ADMIN and a fresh container each (forced_unavailable needs fusectl unmounted) nightly slow and heavy, run together on the nightly runner @@ -36,11 +36,14 @@ MANIFEST = ROOT / "core" / "Cargo.toml" LINUX_ONLY = '#![cfg(target_os = "linux")]' MOUNT_PACKAGE = "layerfs-daemon" +API_MOUNT_TARGETS = {"kernel_mount_routes", "kernel_application", "observed_application", "r5_1_actual_daemon_commit"} # (package, test target): run seconds on the macOS host, 2026-10-23. SLOW = { # Linux native binding proof, owner-excluded from CI; run explicitly. ("layerfs-node", "native_admission"): 60.52, + # Linux SDK mount proof after the ownership move, 2026-10-27. + ("layerfs-api", "observed_application"): 6.30, ("layerfs-api", "scale_lineage_cap"): 24.3, ("layerfs-api", "sdk_merge_scale"): 23.8, ("layerfs-daemon", "complete_installed_roots"): 9.0, @@ -54,7 +57,7 @@ # (package, test target): build CPU seconds in the cold mold build of CI run # 39924955411 (4-CPU runner, test profile without debuginfo). HEAVY = { - ("layerfs-daemon", "mount_control"): 20.6, + ("layerfs-api", "mount_control"): 20.6, ("layerfs-daemon", "store_commit"): 19.1, ("layerfs-workspace", "captured_namespace_cursor"): 9.3, ("layerfs-workspace", "captured_namespace_holds"): 9.0, @@ -74,7 +77,11 @@ } # SDK timings are recorded above without adding the owner-excluded API to CI. -NIGHTLY = {target for target in set(SLOW) | set(HEAVY) if target[0] != "layerfs-node"} +NIGHTLY = { + target + for target in set(SLOW) | set(HEAVY) + if target[0] != "layerfs-node" and not (target[0] == "layerfs-api" and target[1] in API_MOUNT_TARGETS) +} def metadata(): @@ -101,6 +108,9 @@ def test_targets(meta): def mount_targets(meta): found = [] for package, name, source in test_targets(meta): + if package == "layerfs-api" and name in API_MOUNT_TARGETS: + found.append((package, name)) + continue if package != MOUNT_PACKAGE: continue if LINUX_ONLY in source.read_text().splitlines(): diff --git a/core/tools/test_check_product_boundary.py b/core/tools/test_check_product_boundary.py index 9a6f3e149..8ecf49c91 100644 --- a/core/tools/test_check_product_boundary.py +++ b/core/tools/test_check_product_boundary.py @@ -429,13 +429,13 @@ def test_production_and_build_edges_obey_layers(self): if upward: self.assertTrue(any("upward" in reason for _, reason in dependency_violations(source))) - def test_dev_edges_and_temporary_daemon_exception(self): + def test_dev_edges_reject_all_upward_dependencies(self): for table in ("dev-dependencies", "target.'cfg(unix)'.dev-dependencies"): for name, dependency, upward in ( ("layerfs-content", "layerfs-storage", False), ("layerfs-content", "layerfs-project", True), ("layerfs-project", "layerfs-workspace", False), - ("layerfs-daemon", "layerfs-api", False), + ("layerfs-daemon", "layerfs-api", True), ("layerfs-workspace", "layerfs-api", True), ("layerfs-node", "layerfs-api", False), ): @@ -454,7 +454,7 @@ def test_core_rejects_sqlite_in_every_dependency_kind(self): dependency_violations('[package]\nname="layerfs-persistence"\n[dev-dependencies]\nrusqlite="1"') ) - def test_path_escape_and_narrow_exception(self): + def test_path_escape_rejects_all_upward_includes(self): with TemporaryDirectory() as directory: core = Path(directory) / "core" packages = { @@ -470,9 +470,9 @@ def test_path_escape_and_narrow_exception(self): cases = ( (content / "tests/read.rs", storage / "tests/helper.rs", False), (content / "tests/read.rs", api / "tests/helper.rs", True), - (daemon / "tests/merge_report.rs", api / "tests/support/sdk.rs", False), - (daemon / "tests/concurrent_commits.rs", api / "tests/support/installed_store.rs", False), - (daemon / "tests/lane_merge.rs", api / "tests/support/sdk.rs", False), + (daemon / "tests/merge_report.rs", api / "tests/support/sdk.rs", True), + (daemon / "tests/concurrent_commits.rs", api / "tests/support/installed_store.rs", True), + (daemon / "tests/lane_merge.rs", api / "tests/support/sdk.rs", True), (daemon / "tests/other.rs", api / "tests/support/sdk.rs", True), (daemon / "tests/merge_report.rs", api / "tests/other.rs", True), ) diff --git a/core/tools/test_ci_tests.py b/core/tools/test_ci_tests.py index 29090aac7..3f3d3f398 100644 --- a/core/tools/test_ci_tests.py +++ b/core/tools/test_ci_tests.py @@ -27,20 +27,22 @@ def test_fast_targets_leave_out_every_nightly_and_mount_target(self): self.assertEqual(flags.count("--test"), len({name for _, name in fast})) self.assertNotIn("mount_control", flags) - def test_mount_group_is_the_linux_only_daemon_targets(self): + def test_mount_group_includes_moved_sdk_targets(self): mount = ci_tests.mount_targets(self.meta) names = {name for _, name in mount} self.assertIn("forced_unavailable", names) self.assertIn("kernel_application", names) self.assertNotIn("lane_merge", names) - self.assertTrue(all(package == "layerfs-daemon" for package, _ in mount)) + self.assertIn(("layerfs-api", "kernel_application"), mount) + self.assertIn(("layerfs-api", "observed_application"), mount) + self.assertIn(("layerfs-daemon", "forced_unavailable"), mount) def test_fast_filter_excludes_the_nightly_groups_and_nightly_selects_them(self): fast = ci_tests.filter_for("fast", self.meta) nightly = ci_tests.filter_for("nightly", self.meta) self.assertTrue(fast.startswith("not (")) self.assertIn("binary_id(layerfs-api::scale_lineage_cap)", fast) - self.assertIn("binary_id(layerfs-daemon::mount_control)", fast) + self.assertIn("binary_id(layerfs-api::mount_control)", fast) self.assertIn("binary_id(layerfs-daemon::forced_unavailable)", fast) self.assertNotIn("forced_unavailable", nightly) self.assertEqual(nightly.count("binary_id("), len(ci_tests.NIGHTLY)) From ce2c0eb411d5d588b7d9c5754fb2217ac414c264 Mon Sep 17 00:00:00 2001 From: YifanXu1999 Date: Tue, 27 Oct 2026 03:00:32 +0800 Subject: [PATCH 05/10] refactor(463): relocate engine and API below the root workspace Keep the four algorithm crates in core, move nine engine crates and the Rust API to their selected layers, and move the manifest, lock, nextest, tools and authorized fuser package/provenance to their owning roots. Fix relative manifests, test includes, launcher input/target paths, native scripts and CI path selection. The fixture-seal test now locates the root manifest and scans the relocated first-party roots; it retains every original assertion. Its initial path failure is retained, the repaired case passes, and its five unchanged passing cases reuse their initial proof. The root LOC counter retains both layouts and assigns crates by name. All 954 production files retain identical body bytes and per-file LOC; 572 are relocated. Cargo metadata retains the same fifteen packages, first-party edges (including kinds, targets and aliases), package/dependency features and versions. The lockfile and third-party package bytes are unchanged. Only the redundant core tooling counter is deleted. No tests deleted. All moved files are detected as renames with -M20%; the two extensively rewritten path manifests fall below Git's default similarity threshold. The fixture-seal scan-root assumption is an additional live path hit found by execution beyond the spec's initial inventory. Other edits are in its listed path/tool scope. Exact path, body, graph and LOC receipts are retained outside Git. Checks: root all-target no-run build and warning-denying Clippy for all fifteen packages; per-executable Linux tests under 100-second ceilings; native script and paired daemon/addon SDK build; full boundary and fuser provenance guards; 154 combined Python self-tests; Rust fmt, pinned Ruff format and whitespace. The unchanged FP-21 test retains its original FAIL under the explicit owner verification exception and is not rerun. Only this worktree's resource record was prepared for the new target path. Other owners confirmed ready to rebase; their branches/records are untouched. Production LOC: 102162 -> 102162 (delta +0) Scope: all first-party product implementation, including shipped SQL and JavaScript. before: api 7281, core 38241, engine 56640. after: api 7281, core 38241, engine 56640. Method: tools/production_loc.py --json; exact parent and staged trees; inline tests/comments excluded; shipped SQL and JS included. Counter SHA256: 2903e1aed42f0eebb022b82b5fc2220278ccb870bbc06389adc79c4d340bad59. The new counter classifies crates by name in both old and new layouts. reference absent (retired R9c; last counted 65,417 at tree 498dd1917812). --- .cargo/config.toml | 6 +- {core/.config => .config}/nextest.toml | 2 +- .github/workflows/ci.yml | 43 +++-- .github/workflows/format.yml | 2 - .github/workflows/nightly.yml | 22 +-- .gitignore | 2 +- core/Cargo.lock => Cargo.lock | 0 Cargo.toml | 31 ++++ .../sdk/test/verify/direct_refusal_real.mjs | 4 +- .../test/verify/exec_mount_lookup_real.mjs | 2 +- .../sdk/test/verify/exec_output_real.mjs | 2 +- api/agent/sdk/test/verify/reap_real.mjs | 2 +- api/binding/Cargo.toml | 14 +- api/layerfs-api/Cargo.toml | 29 ++++ .../layerfs-api/examples/issue367_rm_probe.rs | 0 .../examples/sandbox_kernel_mount.rs | 0 .../layerfs-api/examples/sandbox_lifecycle.rs | 0 .../layerfs-api/src/base/args.rs | 0 .../layerfs-api/src/base/control.rs | 0 .../layerfs-api/src/base/dispatch.rs | 0 .../layerfs-api/src/base/failure.rs | 0 .../layerfs-api/src/base/internal.rs | 0 .../layerfs-api/src/base/mod.rs | 0 .../layerfs-api/src/base/recovery.rs | 0 .../layerfs-api/src/base/sdk.rs | 0 .../layerfs-api/src/branch/diff_branches.rs | 0 .../layerfs-api/src/branch/diff_commits.rs | 0 .../layerfs-api/src/branch/fork.rs | 0 .../layerfs-api/src/branch/list_commits.rs | 0 .../layerfs-api/src/branch/merge.rs | 0 .../layerfs-api/src/branch/mod.rs | 0 .../layerfs-api/src/branch/publish.rs | 0 .../layerfs-api/src/fs/apply.rs | 0 .../layerfs-api/src/fs/blame.rs | 0 {core/crates => api}/layerfs-api/src/fs/cp.rs | 0 .../layerfs-api/src/fs/diff_files.rs | 0 .../crates => api}/layerfs-api/src/fs/edit.rs | 0 .../crates => api}/layerfs-api/src/fs/glob.rs | 0 .../crates => api}/layerfs-api/src/fs/grep.rs | 0 .../crates => api}/layerfs-api/src/fs/list.rs | 0 .../layerfs-api/src/fs/mkdir.rs | 0 .../crates => api}/layerfs-api/src/fs/mod.rs | 0 {core/crates => api}/layerfs-api/src/fs/mv.rs | 0 .../crates => api}/layerfs-api/src/fs/read.rs | 0 {core/crates => api}/layerfs-api/src/fs/rm.rs | 0 .../crates => api}/layerfs-api/src/fs/stat.rs | 0 .../layerfs-api/src/fs/write.rs | 0 {core/crates => api}/layerfs-api/src/lib.rs | 0 .../layerfs-api/src/operator/call.rs | 0 .../layerfs-api/src/operator/inspect/mod.rs | 0 .../src/operator/inspect/snapshot.rs | 0 .../layerfs-api/src/operator/mod.rs | 0 .../layerfs-api/src/project/list_branches.rs | 0 .../layerfs-api/src/project/mod.rs | 0 .../layerfs-api/src/sandbox/close.rs | 0 .../layerfs-api/src/sandbox/commit.rs | 0 .../layerfs-api/src/sandbox/create.rs | 0 .../layerfs-api/src/sandbox/exec.rs | 0 .../layerfs-api/src/sandbox/mod.rs | 0 .../layerfs-api/src/sandbox/mount.rs | 0 .../layerfs-api/src/sandbox/status.rs | 0 .../layerfs-api/src/sandbox/unmount.rs | 0 .../layerfs-api/src/sandbox/values.rs | 0 .../layerfs-api/tests/concurrent_commits.rs | 0 .../layerfs-api/tests/diff_replay.rs | 0 .../layerfs-api/tests/diff_resume.rs | 0 .../tests/fixtures/merge-forms-root.sqlite | Bin .../layerfs-api/tests/golden/sdk_methods.txt | 0 .../tests/history_ancestry_oracle.rs | 0 .../layerfs-api/tests/history_diff_oracle.rs | 0 .../crates => api}/layerfs-api/tests/init.rs | 0 .../layerfs-api/tests/kernel_application.rs | 2 +- .../layerfs-api/tests/kernel_mount_routes.rs | 4 +- .../layerfs-api/tests/lane_merge.rs | 0 .../layerfs-api/tests/local_install.rs | 0 .../layerfs-api/tests/merge_by_serial.rs | 0 .../layerfs-api/tests/merge_forms_fixture.rs | 0 .../layerfs-api/tests/merge_metadata_only.rs | 0 .../layerfs-api/tests/merge_mixed_forms.rs | 0 .../layerfs-api/tests/merge_report.rs | 0 .../layerfs-api/tests/merge_root_oracle.rs | 0 .../layerfs-api/tests/merge_units.rs | 0 .../layerfs-api/tests/method_refusal_order.rs | 0 .../layerfs-api/tests/mount_control.rs | 6 +- .../layerfs-api/tests/observed_application.rs | 2 +- .../layerfs-api/tests/observed_control.rs | 0 .../layerfs-api/tests/operator_history.rs | 0 .../tests/r5_1_actual_daemon_commit.rs | 10 +- .../layerfs-api/tests/refresh_lookups.rs | 0 .../layerfs-api/tests/relink_commit.rs | 0 .../layerfs-api/tests/replay_merges.rs | 0 .../layerfs-api/tests/sandbox_operations.rs | 2 +- .../layerfs-api/tests/scale_lineage_cap.rs | 0 .../layerfs-api/tests/sdk_branch_count.rs | 0 .../layerfs-api/tests/sdk_chunk_deltas.rs | 0 .../layerfs-api/tests/sdk_compare.rs | 0 .../layerfs-api/tests/sdk_diff_entries.rs | 0 .../layerfs-api/tests/sdk_diff_pages.rs | 0 .../layerfs-api/tests/sdk_diff_size.rs | 0 .../layerfs-api/tests/sdk_fixed_costs.rs | 0 .../layerfs-api/tests/sdk_fs_reads_replay.rs | 0 .../layerfs-api/tests/sdk_grep_reads.rs | 0 .../layerfs-api/tests/sdk_history_depth.rs | 0 .../layerfs-api/tests/sdk_list_entries.rs | 0 .../tests/sdk_merge_diagnostics.rs | 0 .../layerfs-api/tests/sdk_merge_paths.rs | 0 .../layerfs-api/tests/sdk_merge_scale.rs | 0 .../layerfs-api/tests/sdk_method_golden.rs | 0 .../layerfs-api/tests/sdk_mount_lookup.rs | 0 .../layerfs-api/tests/sdk_project_count.rs | 0 .../tests/sdk_reads_during_publish.rs | 0 .../tests/sdk_reads_under_publish.rs | 0 .../layerfs-api/tests/sdk_text_scan.rs | 0 .../layerfs-api/tests/sdk_timing_coverage.rs | 0 .../layerfs-api/tests/sdk_written_back.rs | 0 .../tests/support/daemon_binary.rs | 0 .../tests/support/installed_store.rs | 0 .../layerfs-api/tests/support/sdk.rs | 0 .../layerfs-api/tests/support/view.rs | 0 .../tests/workspace_reader_cache.rs | 0 .../layerfs-api/tests/write_cost.rs | 0 .../layerfs-api/tests/write_refusals.rs | 0 api/scripts/build-native.mjs | 4 +- core/Cargo.toml | 49 ------ core/crates/layerfs-api/Cargo.toml | 29 ---- .../layerfs-content/tests/fixture_seal.rs | 25 +-- .../examples/timer_composition.rs | 4 +- .../examples/timer_nested.rs | 2 +- core/tools/production_loc.py | 152 ------------------ .../crates/layerfs-bridge/Cargo.toml | 4 +- .../crates/layerfs-bridge/src/control.rs | 0 .../layerfs-bridge/src/control_forced.rs | 0 .../layerfs-bridge/src/control_history.rs | 0 .../layerfs-bridge/src/control_merge.rs | 0 .../layerfs-bridge/src/control_mount.rs | 0 .../layerfs-bridge/src/control_reply.rs | 0 .../layerfs-bridge/src/control_request.rs | 0 .../crates/layerfs-bridge/src/control_sdk.rs | 0 .../layerfs-bridge/src/control_types.rs | 0 .../layerfs-bridge/src/control_unmount.rs | 0 .../crates/layerfs-bridge/src/daemon_setup.rs | 0 .../crates/layerfs-bridge/src/daemon_types.rs | 0 .../crates/layerfs-bridge/src/daemon_wire.rs | 0 .../layerfs-bridge/src/duplex/channel.rs | 0 .../layerfs-bridge/src/duplex/ending.rs | 0 .../crates/layerfs-bridge/src/duplex/error.rs | 0 .../layerfs-bridge/src/duplex/handshake.rs | 0 .../crates/layerfs-bridge/src/duplex/io.rs | 0 .../crates/layerfs-bridge/src/duplex/mod.rs | 0 .../layerfs-bridge/src/duplex/profile.rs | 0 .../crates/layerfs-bridge/src/duplex/types.rs | 0 .../layerfs-bridge/src/initial_record.rs | 0 .../crates/layerfs-bridge/src/lib.rs | 0 .../crates/layerfs-bridge/src/provision.rs | 0 .../layerfs-bridge/src/provision_wire.rs | 0 .../layerfs-bridge/src/sdk_merge_values.rs | 0 .../crates/layerfs-bridge/src/sdk_values.rs | 0 .../crates/layerfs-bridge/src/wire.rs | 0 .../layerfs-bridge/tests/control_records.rs | 0 .../crates/layerfs-bridge/tests/duplex.rs | 0 .../layerfs-bridge/tests/install_records.rs | 0 .../layerfs-bridge/tests/observed_records.rs | 0 .../layerfs-bridge/tests/sdk_merge_values.rs | 0 .../crates/layerfs-daemon/Cargo.toml | 8 +- .../examples/e2_startup/json.rs | 0 .../examples/e2_startup/records.rs | 0 .../examples/resource_growth.rs | 0 .../examples/resource_growth/allocation.rs | 0 .../examples/resource_growth/observe.rs | 0 .../examples/resource_growth/operations.rs | 0 .../examples/resource_prepare.rs | 0 .../examples/store_accounting.rs | 0 .../examples/store_accounting/produce.rs | 0 .../examples/store_accounting/records.rs | 0 .../layerfs-daemon/src/application/bodies.rs | 0 .../layerfs-daemon/src/application/cli.rs | 0 .../layerfs-daemon/src/application/config.rs | 0 .../src/application/connection.rs | 0 .../src/application/diagnostics.rs | 0 .../src/application/diagnostics/kernel.rs | 0 .../src/application/diagnostics/resources.rs | 0 .../src/application/diagnostics/schema.rs | 0 .../layerfs-daemon/src/application/failure.rs | 0 .../src/application/filesystem.rs | 0 .../layerfs-daemon/src/application/idle.rs | 0 .../layerfs-daemon/src/application/mod.rs | 0 .../layerfs-daemon/src/application/owner.rs | 0 .../layerfs-daemon/src/application/serve.rs | 0 .../layerfs-daemon/src/bin/layerfs-daemon.rs | 0 .../layerfs-daemon/src/control/attach.rs | 0 .../layerfs-daemon/src/control/cleanup.rs | 0 .../layerfs-daemon/src/control/detach.rs | 0 .../layerfs-daemon/src/control/dirty.rs | 0 .../layerfs-daemon/src/control/failure.rs | 0 .../layerfs-daemon/src/control/force.rs | 0 .../layerfs-daemon/src/control/inspect.rs | 0 .../layerfs-daemon/src/control/invalidate.rs | 0 .../layerfs-daemon/src/control/kernel.rs | 0 .../crates/layerfs-daemon/src/control/mod.rs | 0 .../layerfs-daemon/src/control/observation.rs | 0 .../layerfs-daemon/src/control/operations.rs | 0 .../layerfs-daemon/src/control/registry.rs | 0 .../layerfs-daemon/src/control/serve.rs | 0 .../layerfs-daemon/src/control/serving.rs | 0 .../layerfs-daemon/src/control/status.rs | 0 .../layerfs-daemon/src/control/types.rs | 0 .../layerfs-daemon/src/control/unmount.rs | 0 .../crates/layerfs-daemon/src/install.rs | 0 .../crates/layerfs-daemon/src/install_file.rs | 0 .../layerfs-daemon/src/install_types.rs | 0 .../crates/layerfs-daemon/src/lib.rs | 0 .../layerfs-daemon/src/operator/dispatch.rs | 0 .../crates/layerfs-daemon/src/operator/mod.rs | 0 .../layerfs-daemon/src/operator/workspace.rs | 0 .../src/service/filesystem_port.rs | 0 .../crates/layerfs-daemon/src/service/mod.rs | 0 .../crates/layerfs-daemon/src/telemetry.rs | 0 .../tests/complete_installed_roots.rs | 0 .../tests/f046_fork_reference.rs | 0 .../layerfs-daemon/tests/file_digests.rs | 0 .../layerfs-daemon/tests/forced_producers.rs | 0 .../layerfs-daemon/tests/forced_smoke.rs | 0 .../tests/forced_unavailable.rs | 0 .../layerfs-daemon/tests/forced_unmount.rs | 0 .../tests/fp21_detach_stages.rs | 0 .../tests/fp27_reader_health.rs | 0 .../tests/fp2_negotiation_flags.rs | 2 +- .../tests/fp31_forget_underflow.rs | 0 .../layerfs-daemon/tests/host_handoff.rs | 0 .../layerfs-daemon/tests/host_install.rs | 0 .../layerfs-daemon/tests/installed_store.rs | 0 .../layerfs-daemon/tests/kernel_coherence.rs | 0 .../layerfs-daemon/tests/kernel_custody.rs | 0 .../layerfs-daemon/tests/kernel_mount.rs | 0 .../layerfs-daemon/tests/kernel_mutation.rs | 0 .../layerfs-daemon/tests/mounted_commit.rs | 0 .../tests/mounted_commit_failures.rs | 0 .../tests/mounted_concurrency.rs | 0 .../layerfs-daemon/tests/mounted_cycles.rs | 0 .../layerfs-daemon/tests/mounted_drain.rs | 0 .../layerfs-daemon/tests/mounted_execute.rs | 0 .../tests/mounted_failure_scope.rs | 0 .../layerfs-daemon/tests/mounted_fusectl.rs | 0 .../layerfs-daemon/tests/mounted_install.rs | 0 .../layerfs-daemon/tests/mounted_links.rs | 0 .../tests/mounted_listing_reads.rs | 0 .../layerfs-daemon/tests/mounted_low_water.rs | 0 .../tests/mounted_parallel_commits.rs | 0 .../layerfs-daemon/tests/mounted_patterns.rs | 0 .../tests/mounted_recognizer.rs | 0 .../layerfs-daemon/tests/mounted_rewind.rs | 0 .../tests/mounted_serial_admission.rs | 0 .../tests/mounted_sqlite_full.rs | 0 .../tests/mounted_store_read.rs | 0 .../layerfs-daemon/tests/negative_entries.rs | 0 .../tests/r5_10_producer_profile.rs | 4 +- .../tests/r5_5_install_survival.rs | 0 .../tests/r5_9_dirty_mapping.rs | 0 .../tests/rename_predecessor.rs | 0 .../tests/shared_cache_pressure.rs | 0 .../layerfs-daemon/tests/store_commit.rs | 0 .../tests/store_reader_lifecycle.rs | 0 .../tests/support/captured_drive.rs | 0 .../tests/support/complete_bytes.rs | 0 .../tests/support/complete_fixture.rs | 0 .../tests/support/complete_oracle.rs | 0 .../tests/support/control_fixture.rs | 0 .../tests/support/delete_trace.rs | 0 .../layerfs-daemon/tests/support/fusectl.rs | 0 .../tests/support/held_writer.rs | 0 .../tests/support/history_boundary.rs | 0 .../tests/support/history_gate.rs | 0 .../layerfs-daemon/tests/support/holds.rs | 0 .../tests/support/host_install.rs | 0 .../tests/support/install_docker.rs | 4 +- .../tests/support/installed_store.rs | 0 .../tests/support/long_branch_rig.rs | 0 .../layerfs-daemon/tests/support/mounted.rs | 0 .../tests/support/mounted_commit.rs | 0 .../layerfs-daemon/tests/support/mutating.rs | 0 .../tests/support/namespace_model.rs | 0 .../tests/support/record_counts.rs | 0 .../tests/support/request_path.rs | 0 .../tests/support/request_path_counts/c01.txt | 0 .../tests/support/request_path_counts/c03.txt | 0 .../tests/support/request_path_counts/c04.txt | 0 .../tests/support/request_path_counts/c06.txt | 0 .../tests/support/request_path_counts/c10.txt | 0 .../tests/support/shared_cache_rig.rs | 0 .../tests/support/statement_trace.rs | 0 .../tests/support/store_gate.rs | 0 .../tests/telemetry_recording.rs | 0 .../tests/workspace_databases.rs | 0 .../crates/layerfs-fuse/Cargo.toml | 2 +- .../crates/layerfs-fuse/src/attributes.rs | 0 .../layerfs-fuse/src/coherence/attributes.rs | 0 .../crates/layerfs-fuse/src/coherence/mod.rs | 0 .../layerfs-fuse/src/coherence/pages.rs | 0 .../layerfs-fuse/src/coherence/reply_order.rs | 0 .../layerfs-fuse/src/dispatch/diagnostics.rs | 0 .../crates/layerfs-fuse/src/dispatch/mod.rs | 0 .../layerfs-fuse/src/dispatch/requests.rs | 0 .../crates/layerfs-fuse/src/dispatch/types.rs | 0 .../crates/layerfs-fuse/src/lib.rs | 0 .../crates/layerfs-fuse/src/mount/mod.rs | 0 .../crates/layerfs-fuse/src/mount/profile.rs | 0 .../crates/layerfs-fuse/src/mount/syscalls.rs | 0 .../layerfs-fuse/src/operations/create.rs | 0 .../layerfs-fuse/src/operations/directory.rs | 0 .../layerfs-fuse/src/operations/flush.rs | 0 .../layerfs-fuse/src/operations/link.rs | 0 .../layerfs-fuse/src/operations/lookup.rs | 0 .../crates/layerfs-fuse/src/operations/mod.rs | 0 .../layerfs-fuse/src/operations/mutation.rs | 0 .../layerfs-fuse/src/operations/read.rs | 0 .../layerfs-fuse/src/operations/remove.rs | 0 .../layerfs-fuse/src/operations/rename.rs | 0 .../src/operations/unsupported.rs | 0 .../layerfs-fuse/src/operations/write.rs | 0 .../crates/layerfs-fuse/src/phase.rs | 0 .../crates/layerfs-fuse/src/ports.rs | 0 .../layerfs-fuse/src/request/accounting.rs | 0 .../layerfs-fuse/src/request/callbacks.rs | 0 .../layerfs-fuse/src/request/directory.rs | 0 .../layerfs-fuse/src/request/failure.rs | 0 .../crates/layerfs-fuse/src/request/inline.rs | 0 .../crates/layerfs-fuse/src/request/mod.rs | 0 .../crates/layerfs-fuse/src/request/mutate.rs | 0 .../crates/layerfs-fuse/src/request/reply.rs | 0 .../crates/layerfs-fuse/src/request/state.rs | 0 .../layerfs-fuse/src/request/terminal.rs | 0 .../crates/layerfs-fuse/src/session/drain.rs | 0 .../crates/layerfs-fuse/src/session/force.rs | 0 .../layerfs-fuse/src/session/invalidate.rs | 0 .../crates/layerfs-fuse/src/session/mod.rs | 0 .../layerfs-fuse/src/session/startup.rs | 0 .../crates/layerfs-fuse/src/session/state.rs | 0 .../crates/layerfs-fuse/tests/attributes.rs | 0 .../crates/layerfs-fuse/tests/opcode_names.rs | 0 .../crates/layerfs-fuse/tests/opcode_time.rs | 0 .../crates/layerfs-fuse/tests/requests.rs | 0 .../crates/layerfs-overlay/Cargo.toml | 0 .../indexed_operation_record_profile.rs | 0 .../crates/layerfs-overlay/sql/schema.sql | 0 .../layerfs-overlay/src/contract/custody.rs | 0 .../layerfs-overlay/src/contract/error.rs | 0 .../src/contract/indexed_operation_record.rs | 0 .../layerfs-overlay/src/contract/kernel.rs | 0 .../src/contract/kernel_directory.rs | 0 .../layerfs-overlay/src/contract/mod.rs | 0 .../layerfs-overlay/src/contract/types.rs | 0 .../src/database/accounting.rs | 0 .../src/database/connection.rs | 0 .../layerfs-overlay/src/database/mod.rs | 0 .../layerfs-overlay/src/database/physical.rs | 0 .../layerfs-overlay/src/database/profile.rs | 0 .../layerfs-overlay/src/database/startup.rs | 0 .../src/database/statements.rs | 0 .../indexed_operation_record_plan.rs | 0 .../src/diagnostics/metrics.rs | 0 .../layerfs-overlay/src/diagnostics/mod.rs | 0 .../src/diagnostics/payload.rs | 0 .../src/diagnostics/startup.rs | 0 .../crates/layerfs-overlay/src/lib.rs | 0 .../src/lifetime/captured_reader.rs | 0 .../layerfs-overlay/src/lifetime/close.rs | 0 .../src/lifetime/composition.rs | 0 .../src/lifetime/file_owners.rs | 0 .../layerfs-overlay/src/lifetime/frontier.rs | 0 .../src/lifetime/generation.rs | 0 .../src/lifetime/indexed_operation_record.rs | 0 .../layerfs-overlay/src/lifetime/kernel.rs | 0 .../src/lifetime/kernel_cookie.rs | 0 .../src/lifetime/kernel_directory.rs | 0 .../src/lifetime/kernel_directory_read.rs | 0 .../src/lifetime/kernel_file.rs | 0 .../src/lifetime/kernel_mutation.rs | 0 .../src/lifetime/kernel_visit.rs | 0 .../layerfs-overlay/src/lifetime/lookup.rs | 0 .../layerfs-overlay/src/lifetime/mod.rs | 0 .../layerfs-overlay/src/lifetime/operation.rs | 0 .../layerfs-overlay/src/lifetime/orphan.rs | 0 .../layerfs-overlay/src/lifetime/source.rs | 0 .../layerfs-overlay/src/lifetime/tickets.rs | 0 .../layerfs-overlay/src/lifetime/workspace.rs | 0 .../src/maintenance/garbage.rs | 0 .../maintenance/indexed_operation_record.rs | 0 .../layerfs-overlay/src/maintenance/mod.rs | 0 .../layerfs-overlay/src/maintenance/orphan.rs | 0 .../layerfs-overlay/src/maintenance/pieces.rs | 0 .../layerfs-overlay/src/maintenance/ready.rs | 0 .../src/maintenance/source_wait.rs | 0 .../layerfs-overlay/src/maintenance/work.rs | 0 .../src/namespace/captured_namespace.rs | 0 .../layerfs-overlay/src/namespace/compound.rs | 0 .../src/namespace/directory_entry.rs | 0 .../layerfs-overlay/src/namespace/inode.rs | 0 .../layerfs-overlay/src/namespace/job_rows.rs | 0 .../layerfs-overlay/src/namespace/mod.rs | 0 .../src/namespace/predecessor.rs | 0 .../crates/layerfs-overlay/src/open/counts.rs | 0 .../layerfs-overlay/src/open/directories.rs | 0 .../crates/layerfs-overlay/src/open/files.rs | 0 .../layerfs-overlay/src/open/journal.rs | 0 .../crates/layerfs-overlay/src/open/kernel.rs | 0 .../crates/layerfs-overlay/src/open/mod.rs | 0 .../layerfs-overlay/src/payload/access.rs | 0 .../src/payload/captured_runs.rs | 0 .../src/payload/captured_types.rs | 0 .../layerfs-overlay/src/payload/cells.rs | 0 .../layerfs-overlay/src/payload/digest.rs | 0 .../layerfs-overlay/src/payload/layers.rs | 0 .../crates/layerfs-overlay/src/payload/mod.rs | 0 .../src/payload/pieces/captured.rs | 0 .../layerfs-overlay/src/payload/pieces/mod.rs | 0 .../src/payload/pieces/moves.rs | 0 .../src/payload/pieces/rows.rs | 0 .../layerfs-overlay/src/payload/runs.rs | 0 .../layerfs-overlay/src/payload/stream.rs | 0 .../tests/allocation_filesystem.rs | 0 .../tests/captured_namespace.rs | 0 .../layerfs-overlay/tests/captured_runs.rs | 0 .../layerfs-overlay/tests/device_fixture.sh | 4 +- .../crates/layerfs-overlay/tests/digests.rs | 0 .../layerfs-overlay/tests/enospc_as_eio.c | 0 .../layerfs-overlay/tests/error_identity.rs | 0 .../tests/indexed_operation_record.rs | 0 .../tests/indexed_operation_record_cursor.rs | 0 .../tests/indexed_operation_record_entries.rs | 0 .../crates/layerfs-overlay/tests/kept_live.rs | 0 .../layerfs-overlay/tests/kernel_memory.rs | 0 .../crates/layerfs-overlay/tests/orphans.rs | 0 .../crates/layerfs-overlay/tests/payload.rs | 0 .../layerfs-overlay/tests/payload_runs.rs | 0 .../tests/payload_support/mod.rs | 0 .../layerfs-overlay/tests/piece_lifetimes.rs | 0 .../crates/layerfs-overlay/tests/pieces.rs | 0 .../crates/layerfs-persistence/Cargo.toml | 8 +- .../crates/layerfs-persistence/README.md | 0 .../examples/explain_reservation.rs | 0 .../examples/issue327_counters_v2.rs | 0 .../examples/issue327_counters_v3.rs | 0 .../examples/issue327_counters_v4.rs | 0 .../examples/issue327_counters_v5.rs | 0 .../examples/issue327_readonly_diagnostic.rs | 0 .../examples/metadata_allocation_probe.rs | 0 .../sqlite/acquisition/queries/abandoned.sql | 0 .../sqlite/acquisition/queries/advance.sql | 0 .../sql/sqlite/acquisition/queries/begin.sql | 0 .../acquisition/queries/bind_host_file.sql | 0 .../acquisition/queries/bindings_first.sql | 0 .../acquisition/queries/bindings_next.sql | 0 .../sql/sqlite/acquisition/queries/charge.sql | 0 .../acquisition/queries/claim_epoch.sql | 0 .../acquisition/queries/complete_file.sql | 0 .../sql/sqlite/acquisition/queries/credit.sql | 0 .../acquisition/queries/directories.sql | 0 .../acquisition/queries/directory_path.sql | 0 .../acquisition/queries/directory_sizes.sql | 0 .../acquisition/queries/discard_entries.sql | 0 .../queries/discard_entry_keys.sql | 0 .../queries/discard_entry_tail.sql | 0 .../acquisition/queries/discard_host_file.sql | 0 .../queries/discard_host_file_keys.sql | 0 .../queries/discard_host_file_tail.sql | 0 .../acquisition/queries/entries_first.sql | 0 .../acquisition/queries/entries_next.sql | 0 .../queries/entry_dependencies.sql | 0 .../sqlite/acquisition/queries/file_roots.sql | 0 .../sql/sqlite/acquisition/queries/job.sql | 0 .../sqlite/acquisition/queries/job_sizes.sql | 0 .../sql/sqlite/acquisition/queries/jobs.sql | 0 .../sql/sqlite/acquisition/queries/owner.sql | 0 .../acquisition/queries/place_entry.sql | 0 .../acquisition/queries/put_entries.sql | 0 .../sqlite/acquisition/queries/put_entry.sql | 0 .../acquisition/queries/put_host_file.sql | 0 .../sqlite/acquisition/queries/release.sql | 0 .../acquisition/queries/release_abandoned.sql | 0 .../queries/set_directory_root.sql | 0 .../acquisition/queries/unplaced_first.sql | 0 .../acquisition/queries/unplaced_next.sql | 0 .../sql/sqlite/acquisition/schema.sql | 0 .../sql/sqlite/file_digest.sql | 0 .../sql/sqlite/history.sql | 0 .../sql/sqlite/lineage.sql | 0 .../sql/sqlite/merge_scratch.sql | 0 .../sql/sqlite/metadata.sql | 0 .../sql/sqlite/objects.sql | 0 .../sql/sqlite/objects_units.sql | 0 .../sql/sqlite/objects_units_index.sql | 0 .../history/allocation_advance_scope.sql | 0 .../history/allocation_insert_scope.sql | 0 .../history/allocation_scope_by_id.sql | 0 .../queries/history/branch_branch_by_id.sql | 0 .../queries/history/branch_branch_by_name.sql | 0 .../history/branch_branch_first_page.sql | 0 .../history/branch_branch_name_taken.sql | 0 .../history/branch_branch_next_page.sql | 0 .../queries/history/branch_insert_branch.sql | 0 .../queries/history/commit_advance_branch.sql | 0 .../queries/history/commit_commit_by_id.sql | 0 .../queries/history/commit_insert_commit.sql | 0 .../sqlite/queries/history/digest_insert.sql | 0 .../sql/sqlite/queries/history/digest_of.sql | 0 .../queries/history/hint_bindings_of.sql | 0 .../queries/history/hint_insert_binding.sql | 0 .../history/layerstack_advance_stack.sql | 0 .../history/layerstack_insert_layer.sql | 0 .../history/layerstack_insert_stack.sql | 0 .../history/layerstack_layer_by_id.sql | 0 .../history/layerstack_layer_by_source.sql | 0 .../queries/history/layerstack_layer_root.sql | 0 .../history/layerstack_stack_by_id.sql | 0 .../history/layerstack_stack_by_name.sql | 0 .../history/layerstack_stack_first_page.sql | 0 .../queries/history/layerstack_stack_head.sql | 0 .../history/layerstack_stack_name_taken.sql | 0 .../history/layerstack_stack_next_page.sql | 0 .../sqlite/queries/history/lineage_absorb.sql | 0 .../history/lineage_absorbed_below.sql | 0 .../history/lineage_absorbed_height.sql | 0 .../sqlite/queries/history/lineage_commit.sql | 0 .../queries/history/lineage_commit_at.sql | 0 .../queries/history/lineage_insert_commit.sql | 0 .../queries/history/lineage_insert_layer.sql | 0 .../sqlite/queries/history/lineage_layer.sql | 0 .../queries/history/lineage_layers_above.sql | 0 .../sqlite/queries/history/lineage_merges.sql | 0 .../sqlite/queries/history/lineage_reach.sql | 0 .../queries/history/lineage_reach_insert.sql | 0 .../queries/history/lineage_reach_prune.sql | 0 .../history/statistics_record_init.sql | 0 .../queries/history/statistics_totals.sql | 0 .../layerfs-persistence/src/backend/mod.rs | 0 .../src/backend/records.rs | 0 .../backend/sqlite/acquisition/accounting.rs | 0 .../src/backend/sqlite/acquisition/cleanup.rs | 0 .../sqlite/acquisition/entry_windows.rs | 0 .../backend/sqlite/acquisition/metadata.rs | 0 .../src/backend/sqlite/acquisition/mod.rs | 0 .../src/backend/sqlite/acquisition/reads.rs | 0 .../sqlite/acquisition/root_windows.rs | 0 .../backend/sqlite/acquisition/statements.rs | 0 .../src/backend/sqlite/acquisition/writes.rs | 0 .../src/backend/sqlite/admission.rs | 0 .../src/backend/sqlite/connection.rs | 0 .../src/backend/sqlite/file_control.rs | 0 .../src/backend/sqlite/lane.rs | 0 .../src/backend/sqlite/metadata_allocation.rs | 0 .../src/backend/sqlite/metadata_locations.rs | 0 .../src/backend/sqlite/metadata_policy.rs | 0 .../src/backend/sqlite/metadata_signatures.rs | 0 .../src/backend/sqlite/metadata_values.rs | 0 .../src/backend/sqlite/mod.rs | 0 .../src/backend/sqlite/objects_read.rs | 0 .../src/backend/sqlite/objects_selection.rs | 0 .../src/backend/sqlite/prepared.rs | 0 .../src/backend/sqlite/profile.rs | 0 .../src/backend/sqlite/publish.rs | 0 .../src/backend/sqlite/query.rs | 0 .../src/backend/sqlite/reclamation.rs | 0 .../src/backend/sqlite/rows.rs | 0 .../src/backend/sqlite/schema.rs | 0 .../src/backend/sqlite/seal.rs | 0 .../src/backend/sqlite/seal_allocation.rs | 0 .../src/backend/sqlite/statement_work.rs | 0 .../src/backend/sqlite/thread_work.rs | 0 .../src/backend/sqlite/transaction.rs | 0 .../src/backend/sqlite/unit_io.rs | 0 .../src/backend/sqlite/unit_layout.rs | 0 .../src/backend/sqlite/units_publish.rs | 0 .../src/backend/sqlite/units_read.rs | 0 .../src/backend/sqlite/writer_admission.rs | 0 .../src/history/allocation.rs | 0 .../src/history/ancestry.rs | 0 .../src/history/bindings.rs | 0 .../layerfs-persistence/src/history/branch.rs | 0 .../src/history/catalog.rs | 0 .../layerfs-persistence/src/history/commit.rs | 0 .../src/history/digests.rs | 0 .../layerfs-persistence/src/history/facts.rs | 0 .../layerfs-persistence/src/history/hints.rs | 0 .../src/history/layerstack.rs | 0 .../src/history/lineage.rs | 0 .../src/history/lineage_backfill.rs | 0 .../layerfs-persistence/src/history/merge.rs | 0 .../layerfs-persistence/src/history/mod.rs | 0 .../src/history/provider.rs | 0 .../layerfs-persistence/src/history/rows.rs | 0 .../src/history/transaction.rs | 0 .../crates/layerfs-persistence/src/lib.rs | 0 .../src/metadata/allocation.rs | 0 .../src/metadata/locations.rs | 0 .../layerfs-persistence/src/metadata/mod.rs | 0 .../src/metadata/policy.rs | 0 .../src/metadata/signatures.rs | 0 .../src/metadata/values.rs | 0 .../layerfs-persistence/src/objects/mod.rs | 0 .../layerfs-persistence/src/objects/read.rs | 0 .../src/storage/acquisition/mod.rs | 0 .../src/storage/acquisition/provider.rs | 0 .../src/storage/merge_records.rs | 0 .../layerfs-persistence/src/storage/mod.rs | 0 .../src/storage/provider.rs | 0 .../src/storage/publication.rs | 0 .../layerfs-persistence/src/store/config.rs | 0 .../layerfs-persistence/src/store/handles.rs | 0 .../layerfs-persistence/src/store/mod.rs | 0 .../layerfs-persistence/src/store/open.rs | 0 .../layerfs-persistence/src/store/seal.rs | 0 .../tests/acquisition_batching.rs | 0 .../tests/acquisition_disposal.rs | 0 .../tests/acquisition_reads.rs | 0 .../tests/concurrent_first_installs.rs | 0 .../tests/concurrent_pooled_saves.rs | 0 .../tests/diagnostics_during_lane.rs | 0 .../tests/disposable_startup_sync.rs | 0 .../layerfs-persistence/tests/file_lengths.rs | 0 .../tests/history_allocation.rs | 0 .../tests/history_remediation.rs | 0 .../immutable_reads_under_reclamation.rs | 0 .../tests/inode_branch_delta_custody.rs | 0 .../tests/interleaved_saves.rs | 0 .../tests/lineage_backfill.rs | 0 .../tests/lineage_backfill_measure.rs | 0 .../tests/merge_records.rs | 0 .../tests/old_format_open.rs | 0 .../tests/seal_allocation.rs | 0 .../tests/semantic_admission.rs | 0 .../tests/serverless_store.rs | 0 .../tests/signature_ring_order.rs | 0 .../tests/space_reclamation.rs | 0 .../tests/sqlite_group_rows.rs | 0 .../tests/sqlite_group_rows_indexed.rs | 0 .../tests/sqlite_inode_values.rs | 0 .../tests/sqlite_lock_custody.rs | 0 .../tests/sqlite_ordinal_lookahead.rs | 0 .../tests/sqlite_pack_selection.rs | 0 .../tests/sqlite_publication.rs | 0 .../tests/sqlite_recovery.rs | 0 .../tests/sqlite_reference_acquisition.rs | 0 .../tests/sqlite_transaction_units.rs | 0 .../layerfs-persistence/tests/support/mod.rs | 0 .../layerfs-persistence/tests/thread_work.rs | 0 .../tests/writer_admission.rs | 0 .../crates/layerfs-project/Cargo.toml | 8 +- .../examples/acquisition_profile.rs | 0 .../examples/benchmark_init.rs | 0 .../examples/durable_init_costs.rs | 0 .../examples/durable_init_costs/vfs.rs | 0 .../history_support/canonical_memo.rs | 0 .../examples/verify_namespace.rs | 0 .../layerfs-project/src/import/backing.rs | 0 .../layerfs-project/src/import/batch.rs | 0 .../layerfs-project/src/import/error.rs | 0 .../layerfs-project/src/import/files.rs | 0 .../layerfs-project/src/import/hints.rs | 0 .../crates/layerfs-project/src/import/init.rs | 0 .../crates/layerfs-project/src/import/mod.rs | 0 .../layerfs-project/src/import/namespace.rs | 0 .../layerfs-project/src/import/observe.rs | 0 .../crates/layerfs-project/src/import/scan.rs | 0 .../layerfs-project/src/import/source.rs | 0 .../crates/layerfs-project/src/import/work.rs | 0 .../crates/layerfs-project/src/lib.rs | 0 .../crates/layerfs-project/src/store/init.rs | 0 .../layerfs-project/src/store/install.rs | 0 .../src/store/install_types.rs | 0 .../crates/layerfs-project/src/store/mod.rs | 0 .../tests/acquisition_custody.rs | 0 .../tests/backed_acquisition.rs | 0 .../layerfs-project/tests/complete_root.rs | 0 .../tests/history_proof_memo.rs | 0 .../layerfs-project/tests/init_counters.rs | 0 .../layerfs-project/tests/init_memory.rs | 0 .../layerfs-project/tests/init_sqlite.rs | 0 .../tests/namespace_scaling.rs | 0 .../tests/support/memory_acquisition.rs | 0 .../tests/support/memory_history.rs | 0 .../tests/support/memory_objects.rs | 0 .../layerfs-project/tests/support/mod.rs | 2 +- .../tests/support/old_snapshot.rs | 0 .../crates/layerfs-sandbox/Cargo.toml | 0 .../examples/engine_streams.rs | 0 .../src/backend/docker/archive.rs | 0 .../src/backend/docker/body.rs | 0 .../src/backend/docker/container.rs | 0 .../src/backend/docker/container_types.rs | 0 .../src/backend/docker/endpoint.rs | 0 .../src/backend/docker/headers.rs | 0 .../src/backend/docker/http.rs | 0 .../src/backend/docker/inspect.rs | 0 .../src/backend/docker/json.rs | 0 .../src/backend/docker/listener.rs | 0 .../layerfs-sandbox/src/backend/docker/mod.rs | 0 .../layerfs-sandbox/src/backend/docker/mux.rs | 0 .../src/backend/docker/request.rs | 0 .../src/backend/docker/socket.rs | 0 .../src/backend/docker/streams.rs | 0 .../src/backend/docker/strings.rs | 0 .../src/backend/docker/topology.rs | 0 .../crates/layerfs-sandbox/src/backend/mod.rs | 0 .../crates/layerfs-sandbox/src/lib.rs | 0 .../layerfs-sandbox/src/types/execution.rs | 0 .../layerfs-sandbox/src/types/failure.rs | 0 .../layerfs-sandbox/src/types/identity.rs | 0 .../crates/layerfs-sandbox/src/types/mod.rs | 0 .../layerfs-sandbox/src/types/transfer.rs | 0 .../layerfs-sandbox/tests/container_labels.rs | 0 .../layerfs-sandbox/tests/docker_naming.rs | 0 .../layerfs-sandbox/tests/engine_keepalive.rs | 0 .../layerfs-sandbox/tests/engine_lifecycle.rs | 0 .../layerfs-sandbox/tests/engine_protocol.rs | 0 .../layerfs-sandbox/tests/support/engine.rs | 0 .../crates/layerfs-store-service/Cargo.toml | 8 +- .../layerfs-store-service/src/bootstrap.rs | 0 .../src/history/branch.rs | 0 .../src/history/lookup.rs | 0 .../layerfs-store-service/src/history/mod.rs | 0 .../src/history/units.rs | 0 .../layerfs-store-service/src/install.rs | 0 .../layerfs-store-service/src/kernel_guard.rs | 0 .../crates/layerfs-store-service/src/lib.rs | 0 .../src/operator/args.rs | 0 .../src/operator/dispatch.rs | 0 .../src/operator/files.rs | 0 .../src/operator/inspect.rs | 0 .../layerfs-store-service/src/operator/mod.rs | 0 .../src/operator/store.rs | 0 .../src/overlay/backing.rs | 0 .../src/overlay/captured_namespace_port.rs | 0 .../src/overlay/captured_run_port.rs | 0 .../src/overlay/file_port.rs | 0 .../src/overlay/kernel_operations.rs | 0 .../src/overlay/lifetime_operations.rs | 0 .../layerfs-store-service/src/overlay/mod.rs | 0 .../src/overlay/operation_record_port.rs | 0 .../src/overlay/owner.rs | 0 .../src/overlay/read_operations.rs | 0 .../src/overlay/read_port.rs | 0 .../src/overlay/scopes.rs | 0 .../src/overlay/state.rs | 0 .../src/overlay/workspaces.rs | 0 .../layerfs-store-service/src/read/blame.rs | 0 .../layerfs-store-service/src/read/cached.rs | 0 .../layerfs-store-service/src/read/compare.rs | 0 .../layerfs-store-service/src/read/mod.rs | 0 .../layerfs-store-service/src/read/plans.rs | 0 .../layerfs-store-service/src/read/reads.rs | 0 .../layerfs-store-service/src/read/search.rs | 0 .../src/read/snapshot.rs | 0 .../layerfs-store-service/src/read/walk.rs | 0 .../layerfs-store-service/src/read/window.rs | 0 .../layerfs-store-service/src/service/mod.rs | 0 .../src/service/observations.rs | 0 .../src/service/owner_work.rs | 0 .../src/service/results.rs | 0 .../src/service/startup.rs | 0 .../layerfs-store-service/src/store/bind.rs | 0 .../src/store/captured.rs | 0 .../layerfs-store-service/src/store/commit.rs | 0 .../src/store/commit_merge.rs | 0 .../src/store/commit_types.rs | 0 .../src/store/digests.rs | 0 .../layerfs-store-service/src/store/hints.rs | 0 .../layerfs-store-service/src/store/mod.rs | 0 .../layerfs-store-service/src/store/open.rs | 0 .../src/store/operation.rs | 0 .../layerfs-store-service/src/store/ports.rs | 0 .../src/store/producer.rs | 0 .../src/store/read_handle.rs | 0 .../src/store/read_service.rs | 0 .../src/store/recognizer.rs | 0 .../layerfs-store-service/src/store/settle.rs | 0 .../src/store/statistics.rs | 0 .../layerfs-store-service/src/store/types.rs | 0 .../src/store_service.rs | 0 .../layerfs-store-service/src/telemetry.rs | 0 .../layerfs-store-service/src/write/edit.rs | 0 .../layerfs-store-service/src/write/files.rs | 0 .../layerfs-store-service/src/write/mod.rs | 0 .../src/write/mutation.rs | 0 .../src/write/recursive.rs | 0 .../layerfs-store-service/tests/kept_plans.rs | 0 .../tests/kernel_guard.rs | 0 .../tests/sdk_root_batches.rs | 0 .../crates/layerfs-workspace/Cargo.toml | 4 +- .../layerfs-workspace/src/base/cache.rs | 0 .../layerfs-workspace/src/base/client.rs | 0 .../crates/layerfs-workspace/src/base/file.rs | 0 .../layerfs-workspace/src/base/links.rs | 0 .../crates/layerfs-workspace/src/base/mod.rs | 0 .../crates/layerfs-workspace/src/base/view.rs | 0 .../src/construction/captured/context.rs | 0 .../src/construction/captured/edges.rs | 0 .../src/construction/captured/mod.rs | 0 .../src/construction/captured/normalize.rs | 0 .../src/construction/captured/owner.rs | 0 .../src/construction/captured/scan.rs | 0 .../src/construction/captured/script.rs | 0 .../src/construction/captured/source.rs | 0 .../src/construction/captured/state.rs | 0 .../src/construction/driver.rs | 0 .../layerfs-workspace/src/construction/mod.rs | 0 .../src/construction/namespace/cursor.rs | 0 .../src/construction/namespace/inodes.rs | 0 .../src/construction/namespace/mod.rs | 0 .../src/construction/namespace/normalize.rs | 0 .../src/construction/namespace/records.rs | 0 .../src/construction/outcome.rs | 0 .../src/construction/records.rs | 0 .../crates/layerfs-workspace/src/lib.rs | 0 .../layerfs-workspace/src/mutation/driver.rs | 0 .../layerfs-workspace/src/mutation/eval.rs | 0 .../layerfs-workspace/src/mutation/facts.rs | 0 .../layerfs-workspace/src/mutation/job.rs | 0 .../layerfs-workspace/src/mutation/mod.rs | 0 .../layerfs-workspace/src/mutation/plan.rs | 0 .../src/operations/attributes.rs | 0 .../src/operations/file/mod.rs | 0 .../src/operations/file/read.rs | 0 .../src/operations/file/recognize.rs | 0 .../src/operations/file/write.rs | 0 .../src/operations/kernel_data.rs | 0 .../src/operations/kernel_directory.rs | 0 .../src/operations/kernel_mutation.rs | 0 .../src/operations/kernel_read.rs | 0 .../src/operations/kernel_visit.rs | 0 .../layerfs-workspace/src/operations/mod.rs | 0 .../src/operations/namespace/create.rs | 0 .../src/operations/namespace/list.rs | 0 .../src/operations/namespace/mod.rs | 0 .../src/operations/namespace/remove.rs | 0 .../src/operations/namespace/rename.rs | 0 .../layerfs-workspace/src/operations/types.rs | 0 .../src/ports/captured_namespace.rs | 0 .../src/ports/captured_runs.rs | 0 .../layerfs-workspace/src/ports/digests.rs | 0 .../layerfs-workspace/src/ports/files.rs | 0 .../layerfs-workspace/src/ports/lengths.rs | 0 .../crates/layerfs-workspace/src/ports/mod.rs | 0 .../src/ports/operation_record.rs | 0 .../layerfs-workspace/src/ports/overlay.rs | 0 .../src/workspace/install.rs | 0 .../layerfs-workspace/src/workspace/mod.rs | 0 .../layerfs-workspace/src/workspace/route.rs | 0 .../src/workspace/serials.rs | 0 .../layerfs-workspace/src/workspace/state.rs | 0 .../layerfs-workspace/src/workspace/view.rs | 0 .../tests/captured_file_edits.rs | 0 .../tests/captured_namespace.rs | 0 .../tests/captured_namespace_cursor.rs | 0 .../tests/captured_namespace_custody.rs | 0 .../tests/captured_namespace_fragments.rs | 0 .../tests/captured_namespace_holds.rs | 0 .../tests/captured_namespace_inline.rs | 0 .../tests/captured_namespace_metadata.rs | 0 .../tests/captured_namespace_order.rs | 0 .../tests/captured_namespace_perturbed.rs | 0 .../tests/captured_namespace_rebound.rs | 0 .../tests/captured_namespace_states.rs | 0 .../tests/captured_new_file_route.rs | 0 .../tests/captured_piece_edits.rs | 0 .../tests/captured_support/mod.rs | 0 .../layerfs-workspace/tests/common/mod.rs | 0 .../layerfs-workspace/tests/decoded_pages.rs | 0 .../tests/directory_links.rs | 0 .../tests/directory_links_install.rs | 0 .../layerfs-workspace/tests/file_lengths.rs | 0 .../layerfs-workspace/tests/harness/mod.rs | 0 .../layerfs-workspace/tests/kernel_data.rs | 0 .../tests/kernel_directory.rs | 0 .../layerfs-workspace/tests/kernel_visit.rs | 0 .../layerfs-workspace/tests/mutation_plan.rs | 0 .../layerfs-workspace/tests/namespace.rs | 0 .../layerfs-workspace/tests/namespace_view.rs | 0 .../crates/layerfs-workspace/tests/nonfile.rs | 0 .../tests/operation_scope.rs | 0 .../layerfs-workspace/tests/oracle/mod.rs | 0 .../crates/layerfs-workspace/tests/payload.rs | 0 .../layerfs-workspace/tests/producer/mod.rs | 0 .../layerfs-workspace/tests/recognize.rs | 0 .../tests/shared_cache_client.rs | 0 .../tests/sibling_lengths.rs | 0 .../patches/fuser-0.18.0/README.md | 0 .../fuser-0.18.0/lifecycle-provenance.json | 0 .../patches/fuser-0.18.0/provenance.json | 0 .../receive-buffer-provenance.json | 0 .../patches/fuser-0.18.0/receive-buffer.patch | 0 .../fuser-0.18.0/session-lifecycle.patch | 0 .../fuser-0.18.0/signed-timestamps.patch | 0 .../vendor/fuser-0.18.0/.cargo_vcs_info.json | 0 .../vendor/fuser-0.18.0/.dockerignore | 0 .../fuser-0.18.0/.github/workflows/ci.yml | 0 .../vendor/fuser-0.18.0/.gitignore | 0 .../vendor/fuser-0.18.0/AGENTS.md | 0 .../vendor/fuser-0.18.0/CHANGELOG.md | 0 .../vendor/fuser-0.18.0/CLAUDE.md | 0 .../vendor/fuser-0.18.0/Cargo.lock | 0 .../vendor/fuser-0.18.0/Cargo.toml | 0 .../vendor/fuser-0.18.0/Cargo.toml.orig | 0 .../vendor/fuser-0.18.0/LICENSE.md | 0 {core => engine}/vendor/fuser-0.18.0/Makefile | 0 .../vendor/fuser-0.18.0/README.md | 0 {core => engine}/vendor/fuser-0.18.0/build.rs | 0 .../vendor/fuser-0.18.0/deny.toml | 0 .../fuser-0.18.0/examples/async_hello.rs | 0 .../fuser-0.18.0/examples/common/args.rs | 0 .../fuser-0.18.0/examples/common/mod.rs | 0 .../vendor/fuser-0.18.0/examples/hello.rs | 0 .../vendor/fuser-0.18.0/examples/ioctl.rs | 0 .../examples/notify_inval_entry.rs | 0 .../examples/notify_inval_inode.rs | 0 .../vendor/fuser-0.18.0/examples/null.rs | 0 .../fuser-0.18.0/examples/passthrough.rs | 0 .../fuser-0.18.0/examples/passthrough_fork.rs | 0 .../vendor/fuser-0.18.0/examples/poll.rs | 0 .../fuser-0.18.0/examples/poll_client.rs | 0 .../vendor/fuser-0.18.0/examples/simple.rs | 0 .../mount_tests_libfuse2.Dockerfile | 0 .../mount_tests_libfuse3.Dockerfile | 0 .../vendor/fuser-0.18.0/pjdfs.Dockerfile | 0 {core => engine}/vendor/fuser-0.18.0/pjdfs.sh | 0 .../vendor/fuser-0.18.0/rust-toolchain | 0 .../vendor/fuser-0.18.0/rustfmt.toml | 0 .../vendor/fuser-0.18.0/src/access_flags.rs | 0 .../vendor/fuser-0.18.0/src/bsd_file_flags.rs | 0 .../vendor/fuser-0.18.0/src/channel.rs | 0 .../vendor/fuser-0.18.0/src/dev_fuse.rs | 0 .../vendor/fuser-0.18.0/src/experimental.rs | 0 .../vendor/fuser-0.18.0/src/forget_one.rs | 0 .../vendor/fuser-0.18.0/src/lib.rs | 0 .../vendor/fuser-0.18.0/src/ll/argument.rs | 0 .../src/ll/flags/copy_file_range_flags.rs | 0 .../src/ll/flags/cuse_init_flags.rs | 0 .../fuser-0.18.0/src/ll/flags/fattr_flags.rs | 0 .../fuser-0.18.0/src/ll/flags/fopen_flags.rs | 0 .../fuser-0.18.0/src/ll/flags/fsync_flags.rs | 0 .../src/ll/flags/getattr_flags.rs | 0 .../fuser-0.18.0/src/ll/flags/init_flags.rs | 0 .../fuser-0.18.0/src/ll/flags/ioctl_flags.rs | 0 .../vendor/fuser-0.18.0/src/ll/flags/mod.rs | 0 .../fuser-0.18.0/src/ll/flags/poll_flags.rs | 0 .../fuser-0.18.0/src/ll/flags/read_flags.rs | 0 .../src/ll/flags/release_flags.rs | 0 .../fuser-0.18.0/src/ll/flags/write_flags.rs | 0 .../vendor/fuser-0.18.0/src/ll/fuse_abi.rs | 0 .../vendor/fuser-0.18.0/src/ll/ioctl.rs | 0 .../fuser-0.18.0/src/ll/ioslice_concat.rs | 0 .../vendor/fuser-0.18.0/src/ll/mod.rs | 0 .../vendor/fuser-0.18.0/src/ll/notify.rs | 0 .../vendor/fuser-0.18.0/src/ll/reply.rs | 0 .../vendor/fuser-0.18.0/src/ll/request.rs | 0 .../vendor/fuser-0.18.0/src/mnt/fuse2.rs | 0 .../vendor/fuser-0.18.0/src/mnt/fuse2_sys.rs | 0 .../vendor/fuser-0.18.0/src/mnt/fuse3.rs | 0 .../vendor/fuser-0.18.0/src/mnt/fuse3_sys.rs | 0 .../vendor/fuser-0.18.0/src/mnt/fuse_pure.rs | 0 .../vendor/fuser-0.18.0/src/mnt/mod.rs | 0 .../fuser-0.18.0/src/mnt/mount_options.rs | 0 .../vendor/fuser-0.18.0/src/notify.rs | 0 .../vendor/fuser-0.18.0/src/open_flags.rs | 0 .../vendor/fuser-0.18.0/src/passthrough.rs | 0 .../vendor/fuser-0.18.0/src/poll_events.rs | 0 .../vendor/fuser-0.18.0/src/read_buf.rs | 0 .../vendor/fuser-0.18.0/src/rename_flags.rs | 0 .../vendor/fuser-0.18.0/src/reply.rs | 0 .../vendor/fuser-0.18.0/src/request.rs | 0 .../vendor/fuser-0.18.0/src/request_param.rs | 0 .../vendor/fuser-0.18.0/src/session.rs | 0 .../fuser-0.18.0/src/session/lifecycle.rs | 0 .../vendor/fuser-0.18.0/src/time.rs | 0 .../vendor/fuser-0.18.0/tests/bsd_pjdfs.sh | 0 .../vendor/fuser-0.18.0/tests/macos_pjdfs.sh | 0 .../fuser-0.18.0/tests/test_passthrough.sh | 0 .../vendor/fuser-0.18.0/xfstests.Dockerfile | 0 .../vendor/fuser-0.18.0/xfstests.sh | 0 ruff.toml | 4 +- .../tools => tools}/check_fuser_integrity.py | 10 +- .../tools => tools}/check_product_boundary.py | 46 ++++-- {core/tools => tools}/ci_tests.py | 6 +- tools/cleanup_discover.py | 1 + tools/decode_observations.py | 2 +- {core/tools => tools}/phase7_services.py | 2 +- tools/preflight.sh | 10 +- tools/production_loc.py | 79 +++++++-- {core/tools => tools}/sdk_telemetry_report.py | 0 tools/stage5_component_comparison.py | 4 +- .../substitution-proof/README.md | 0 .../arms/baseline/Cargo.lock | 0 .../arms/baseline/Cargo.toml | 0 .../arms/c1-only/Cargo.lock | 0 .../arms/c1-only/Cargo.toml | 0 .../arms/c2-only/Cargo.lock | 0 .../arms/c2-only/Cargo.toml | 0 .../arms/combined/Cargo.lock | 0 .../arms/combined/Cargo.toml | 0 .../consumer/core_pipeline.rs | 0 .../consumer/cross_revision.rs | 0 .../filesystem_primitives_candidate.rs | 0 .../consumer/support/filesystem.rs | 0 .../consumer/support/mod.rs | 0 .../substitution-proof/matrix.json | 0 .../tools => tools}/substitution-proof/run.py | 18 +-- .../test_check_fuser_integrity.py | 6 +- .../test_check_product_boundary.py | 74 ++++++--- {core/tools => tools}/test_ci_tests.py | 6 +- tools/test_cleanup.py | 8 +- {core/tools => tools}/test_phase7_services.py | 0 tools/test_production_loc.py | 20 ++- .../test_sdk_telemetry_report.py | 0 tools/test_worktree.py | 28 +++- tools/worktree_build.py | 18 +-- tools/worktree_resources.py | 18 ++- 1015 files changed, 414 insertions(+), 456 deletions(-) rename {core/.config => .config}/nextest.toml (85%) rename core/Cargo.lock => Cargo.lock (100%) create mode 100644 Cargo.toml create mode 100644 api/layerfs-api/Cargo.toml rename {core/crates => api}/layerfs-api/examples/issue367_rm_probe.rs (100%) rename {core/crates => api}/layerfs-api/examples/sandbox_kernel_mount.rs (100%) rename {core/crates => api}/layerfs-api/examples/sandbox_lifecycle.rs (100%) rename {core/crates => api}/layerfs-api/src/base/args.rs (100%) rename {core/crates => api}/layerfs-api/src/base/control.rs (100%) rename {core/crates => api}/layerfs-api/src/base/dispatch.rs (100%) rename {core/crates => api}/layerfs-api/src/base/failure.rs (100%) rename {core/crates => api}/layerfs-api/src/base/internal.rs (100%) rename {core/crates => api}/layerfs-api/src/base/mod.rs (100%) rename {core/crates => api}/layerfs-api/src/base/recovery.rs (100%) rename {core/crates => api}/layerfs-api/src/base/sdk.rs (100%) rename {core/crates => api}/layerfs-api/src/branch/diff_branches.rs (100%) rename {core/crates => api}/layerfs-api/src/branch/diff_commits.rs (100%) rename {core/crates => api}/layerfs-api/src/branch/fork.rs (100%) rename {core/crates => api}/layerfs-api/src/branch/list_commits.rs (100%) rename {core/crates => api}/layerfs-api/src/branch/merge.rs (100%) rename {core/crates => api}/layerfs-api/src/branch/mod.rs (100%) rename {core/crates => api}/layerfs-api/src/branch/publish.rs (100%) rename {core/crates => api}/layerfs-api/src/fs/apply.rs (100%) rename {core/crates => api}/layerfs-api/src/fs/blame.rs (100%) rename {core/crates => api}/layerfs-api/src/fs/cp.rs (100%) rename {core/crates => api}/layerfs-api/src/fs/diff_files.rs (100%) rename {core/crates => api}/layerfs-api/src/fs/edit.rs (100%) rename {core/crates => api}/layerfs-api/src/fs/glob.rs (100%) rename {core/crates => api}/layerfs-api/src/fs/grep.rs (100%) rename {core/crates => api}/layerfs-api/src/fs/list.rs (100%) rename {core/crates => api}/layerfs-api/src/fs/mkdir.rs (100%) rename {core/crates => api}/layerfs-api/src/fs/mod.rs (100%) rename {core/crates => api}/layerfs-api/src/fs/mv.rs (100%) rename {core/crates => api}/layerfs-api/src/fs/read.rs (100%) rename {core/crates => api}/layerfs-api/src/fs/rm.rs (100%) rename {core/crates => api}/layerfs-api/src/fs/stat.rs (100%) rename {core/crates => api}/layerfs-api/src/fs/write.rs (100%) rename {core/crates => api}/layerfs-api/src/lib.rs (100%) rename {core/crates => api}/layerfs-api/src/operator/call.rs (100%) rename {core/crates => api}/layerfs-api/src/operator/inspect/mod.rs (100%) rename {core/crates => api}/layerfs-api/src/operator/inspect/snapshot.rs (100%) rename {core/crates => api}/layerfs-api/src/operator/mod.rs (100%) rename {core/crates => api}/layerfs-api/src/project/list_branches.rs (100%) rename {core/crates => api}/layerfs-api/src/project/mod.rs (100%) rename {core/crates => api}/layerfs-api/src/sandbox/close.rs (100%) rename {core/crates => api}/layerfs-api/src/sandbox/commit.rs (100%) rename {core/crates => api}/layerfs-api/src/sandbox/create.rs (100%) rename {core/crates => api}/layerfs-api/src/sandbox/exec.rs (100%) rename {core/crates => api}/layerfs-api/src/sandbox/mod.rs (100%) rename {core/crates => api}/layerfs-api/src/sandbox/mount.rs (100%) rename {core/crates => api}/layerfs-api/src/sandbox/status.rs (100%) rename {core/crates => api}/layerfs-api/src/sandbox/unmount.rs (100%) rename {core/crates => api}/layerfs-api/src/sandbox/values.rs (100%) rename {core/crates => api}/layerfs-api/tests/concurrent_commits.rs (100%) rename {core/crates => api}/layerfs-api/tests/diff_replay.rs (100%) rename {core/crates => api}/layerfs-api/tests/diff_resume.rs (100%) rename {core/crates => api}/layerfs-api/tests/fixtures/merge-forms-root.sqlite (100%) rename {core/crates => api}/layerfs-api/tests/golden/sdk_methods.txt (100%) rename {core/crates => api}/layerfs-api/tests/history_ancestry_oracle.rs (100%) rename {core/crates => api}/layerfs-api/tests/history_diff_oracle.rs (100%) rename {core/crates => api}/layerfs-api/tests/init.rs (100%) rename {core/crates => api}/layerfs-api/tests/kernel_application.rs (98%) rename {core/crates => api}/layerfs-api/tests/kernel_mount_routes.rs (98%) rename {core/crates => api}/layerfs-api/tests/lane_merge.rs (100%) rename {core/crates => api}/layerfs-api/tests/local_install.rs (100%) rename {core/crates => api}/layerfs-api/tests/merge_by_serial.rs (100%) rename {core/crates => api}/layerfs-api/tests/merge_forms_fixture.rs (100%) rename {core/crates => api}/layerfs-api/tests/merge_metadata_only.rs (100%) rename {core/crates => api}/layerfs-api/tests/merge_mixed_forms.rs (100%) rename {core/crates => api}/layerfs-api/tests/merge_report.rs (100%) rename {core/crates => api}/layerfs-api/tests/merge_root_oracle.rs (100%) rename {core/crates => api}/layerfs-api/tests/merge_units.rs (100%) rename {core/crates => api}/layerfs-api/tests/method_refusal_order.rs (100%) rename {core/crates => api}/layerfs-api/tests/mount_control.rs (99%) rename {core/crates => api}/layerfs-api/tests/observed_application.rs (99%) rename {core/crates => api}/layerfs-api/tests/observed_control.rs (100%) rename {core/crates => api}/layerfs-api/tests/operator_history.rs (100%) rename {core/crates => api}/layerfs-api/tests/r5_1_actual_daemon_commit.rs (97%) rename {core/crates => api}/layerfs-api/tests/refresh_lookups.rs (100%) rename {core/crates => api}/layerfs-api/tests/relink_commit.rs (100%) rename {core/crates => api}/layerfs-api/tests/replay_merges.rs (100%) rename {core/crates => api}/layerfs-api/tests/sandbox_operations.rs (99%) rename {core/crates => api}/layerfs-api/tests/scale_lineage_cap.rs (100%) rename {core/crates => api}/layerfs-api/tests/sdk_branch_count.rs (100%) rename {core/crates => api}/layerfs-api/tests/sdk_chunk_deltas.rs (100%) rename {core/crates => api}/layerfs-api/tests/sdk_compare.rs (100%) rename {core/crates => api}/layerfs-api/tests/sdk_diff_entries.rs (100%) rename {core/crates => api}/layerfs-api/tests/sdk_diff_pages.rs (100%) rename {core/crates => api}/layerfs-api/tests/sdk_diff_size.rs (100%) rename {core/crates => api}/layerfs-api/tests/sdk_fixed_costs.rs (100%) rename {core/crates => api}/layerfs-api/tests/sdk_fs_reads_replay.rs (100%) rename {core/crates => api}/layerfs-api/tests/sdk_grep_reads.rs (100%) rename {core/crates => api}/layerfs-api/tests/sdk_history_depth.rs (100%) rename {core/crates => api}/layerfs-api/tests/sdk_list_entries.rs (100%) rename {core/crates => api}/layerfs-api/tests/sdk_merge_diagnostics.rs (100%) rename {core/crates => api}/layerfs-api/tests/sdk_merge_paths.rs (100%) rename {core/crates => api}/layerfs-api/tests/sdk_merge_scale.rs (100%) rename {core/crates => api}/layerfs-api/tests/sdk_method_golden.rs (100%) rename {core/crates => api}/layerfs-api/tests/sdk_mount_lookup.rs (100%) rename {core/crates => api}/layerfs-api/tests/sdk_project_count.rs (100%) rename {core/crates => api}/layerfs-api/tests/sdk_reads_during_publish.rs (100%) rename {core/crates => api}/layerfs-api/tests/sdk_reads_under_publish.rs (100%) rename {core/crates => api}/layerfs-api/tests/sdk_text_scan.rs (100%) rename {core/crates => api}/layerfs-api/tests/sdk_timing_coverage.rs (100%) rename {core/crates => api}/layerfs-api/tests/sdk_written_back.rs (100%) rename {core/crates => api}/layerfs-api/tests/support/daemon_binary.rs (100%) rename {core/crates => api}/layerfs-api/tests/support/installed_store.rs (100%) rename {core/crates => api}/layerfs-api/tests/support/sdk.rs (100%) rename {core/crates => api}/layerfs-api/tests/support/view.rs (100%) rename {core/crates => api}/layerfs-api/tests/workspace_reader_cache.rs (100%) rename {core/crates => api}/layerfs-api/tests/write_cost.rs (100%) rename {core/crates => api}/layerfs-api/tests/write_refusals.rs (100%) delete mode 100644 core/Cargo.toml delete mode 100644 core/crates/layerfs-api/Cargo.toml delete mode 100644 core/tools/production_loc.py rename {core => engine}/crates/layerfs-bridge/Cargo.toml (78%) rename {core => engine}/crates/layerfs-bridge/src/control.rs (100%) rename {core => engine}/crates/layerfs-bridge/src/control_forced.rs (100%) rename {core => engine}/crates/layerfs-bridge/src/control_history.rs (100%) rename {core => engine}/crates/layerfs-bridge/src/control_merge.rs (100%) rename {core => engine}/crates/layerfs-bridge/src/control_mount.rs (100%) rename {core => engine}/crates/layerfs-bridge/src/control_reply.rs (100%) rename {core => engine}/crates/layerfs-bridge/src/control_request.rs (100%) rename {core => engine}/crates/layerfs-bridge/src/control_sdk.rs (100%) rename {core => engine}/crates/layerfs-bridge/src/control_types.rs (100%) rename {core => engine}/crates/layerfs-bridge/src/control_unmount.rs (100%) rename {core => engine}/crates/layerfs-bridge/src/daemon_setup.rs (100%) rename {core => engine}/crates/layerfs-bridge/src/daemon_types.rs (100%) rename {core => engine}/crates/layerfs-bridge/src/daemon_wire.rs (100%) rename {core => engine}/crates/layerfs-bridge/src/duplex/channel.rs (100%) rename {core => engine}/crates/layerfs-bridge/src/duplex/ending.rs (100%) rename {core => engine}/crates/layerfs-bridge/src/duplex/error.rs (100%) rename {core => engine}/crates/layerfs-bridge/src/duplex/handshake.rs (100%) rename {core => engine}/crates/layerfs-bridge/src/duplex/io.rs (100%) rename {core => engine}/crates/layerfs-bridge/src/duplex/mod.rs (100%) rename {core => engine}/crates/layerfs-bridge/src/duplex/profile.rs (100%) rename {core => engine}/crates/layerfs-bridge/src/duplex/types.rs (100%) rename {core => engine}/crates/layerfs-bridge/src/initial_record.rs (100%) rename {core => engine}/crates/layerfs-bridge/src/lib.rs (100%) rename {core => engine}/crates/layerfs-bridge/src/provision.rs (100%) rename {core => engine}/crates/layerfs-bridge/src/provision_wire.rs (100%) rename {core => engine}/crates/layerfs-bridge/src/sdk_merge_values.rs (100%) rename {core => engine}/crates/layerfs-bridge/src/sdk_values.rs (100%) rename {core => engine}/crates/layerfs-bridge/src/wire.rs (100%) rename {core => engine}/crates/layerfs-bridge/tests/control_records.rs (100%) rename {core => engine}/crates/layerfs-bridge/tests/duplex.rs (100%) rename {core => engine}/crates/layerfs-bridge/tests/install_records.rs (100%) rename {core => engine}/crates/layerfs-bridge/tests/observed_records.rs (100%) rename {core => engine}/crates/layerfs-bridge/tests/sdk_merge_values.rs (100%) rename {core => engine}/crates/layerfs-daemon/Cargo.toml (75%) rename {core => engine}/crates/layerfs-daemon/examples/e2_startup/json.rs (100%) rename {core => engine}/crates/layerfs-daemon/examples/e2_startup/records.rs (100%) rename {core => engine}/crates/layerfs-daemon/examples/resource_growth.rs (100%) rename {core => engine}/crates/layerfs-daemon/examples/resource_growth/allocation.rs (100%) rename {core => engine}/crates/layerfs-daemon/examples/resource_growth/observe.rs (100%) rename {core => engine}/crates/layerfs-daemon/examples/resource_growth/operations.rs (100%) rename {core => engine}/crates/layerfs-daemon/examples/resource_prepare.rs (100%) rename {core => engine}/crates/layerfs-daemon/examples/store_accounting.rs (100%) rename {core => engine}/crates/layerfs-daemon/examples/store_accounting/produce.rs (100%) rename {core => engine}/crates/layerfs-daemon/examples/store_accounting/records.rs (100%) rename {core => engine}/crates/layerfs-daemon/src/application/bodies.rs (100%) rename {core => engine}/crates/layerfs-daemon/src/application/cli.rs (100%) rename {core => engine}/crates/layerfs-daemon/src/application/config.rs (100%) rename {core => engine}/crates/layerfs-daemon/src/application/connection.rs (100%) rename {core => engine}/crates/layerfs-daemon/src/application/diagnostics.rs (100%) rename {core => engine}/crates/layerfs-daemon/src/application/diagnostics/kernel.rs (100%) rename {core => engine}/crates/layerfs-daemon/src/application/diagnostics/resources.rs (100%) rename {core => engine}/crates/layerfs-daemon/src/application/diagnostics/schema.rs (100%) rename {core => engine}/crates/layerfs-daemon/src/application/failure.rs (100%) rename {core => engine}/crates/layerfs-daemon/src/application/filesystem.rs (100%) rename {core => engine}/crates/layerfs-daemon/src/application/idle.rs (100%) rename {core => engine}/crates/layerfs-daemon/src/application/mod.rs (100%) rename {core => engine}/crates/layerfs-daemon/src/application/owner.rs (100%) rename {core => engine}/crates/layerfs-daemon/src/application/serve.rs (100%) rename {core => engine}/crates/layerfs-daemon/src/bin/layerfs-daemon.rs (100%) rename {core => engine}/crates/layerfs-daemon/src/control/attach.rs (100%) rename {core => engine}/crates/layerfs-daemon/src/control/cleanup.rs (100%) rename {core => engine}/crates/layerfs-daemon/src/control/detach.rs (100%) rename {core => engine}/crates/layerfs-daemon/src/control/dirty.rs (100%) rename {core => engine}/crates/layerfs-daemon/src/control/failure.rs (100%) rename {core => engine}/crates/layerfs-daemon/src/control/force.rs (100%) rename {core => engine}/crates/layerfs-daemon/src/control/inspect.rs (100%) rename {core => engine}/crates/layerfs-daemon/src/control/invalidate.rs (100%) rename {core => engine}/crates/layerfs-daemon/src/control/kernel.rs (100%) rename {core => engine}/crates/layerfs-daemon/src/control/mod.rs (100%) rename {core => engine}/crates/layerfs-daemon/src/control/observation.rs (100%) rename {core => engine}/crates/layerfs-daemon/src/control/operations.rs (100%) rename {core => engine}/crates/layerfs-daemon/src/control/registry.rs (100%) rename {core => engine}/crates/layerfs-daemon/src/control/serve.rs (100%) rename {core => engine}/crates/layerfs-daemon/src/control/serving.rs (100%) rename {core => engine}/crates/layerfs-daemon/src/control/status.rs (100%) rename {core => engine}/crates/layerfs-daemon/src/control/types.rs (100%) rename {core => engine}/crates/layerfs-daemon/src/control/unmount.rs (100%) rename {core => engine}/crates/layerfs-daemon/src/install.rs (100%) rename {core => engine}/crates/layerfs-daemon/src/install_file.rs (100%) rename {core => engine}/crates/layerfs-daemon/src/install_types.rs (100%) rename {core => engine}/crates/layerfs-daemon/src/lib.rs (100%) rename {core => engine}/crates/layerfs-daemon/src/operator/dispatch.rs (100%) rename {core => engine}/crates/layerfs-daemon/src/operator/mod.rs (100%) rename {core => engine}/crates/layerfs-daemon/src/operator/workspace.rs (100%) rename {core => engine}/crates/layerfs-daemon/src/service/filesystem_port.rs (100%) rename {core => engine}/crates/layerfs-daemon/src/service/mod.rs (100%) rename {core => engine}/crates/layerfs-daemon/src/telemetry.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/complete_installed_roots.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/f046_fork_reference.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/file_digests.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/forced_producers.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/forced_smoke.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/forced_unavailable.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/forced_unmount.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/fp21_detach_stages.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/fp27_reader_health.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/fp2_negotiation_flags.rs (99%) rename {core => engine}/crates/layerfs-daemon/tests/fp31_forget_underflow.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/host_handoff.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/host_install.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/installed_store.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/kernel_coherence.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/kernel_custody.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/kernel_mount.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/kernel_mutation.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/mounted_commit.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/mounted_commit_failures.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/mounted_concurrency.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/mounted_cycles.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/mounted_drain.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/mounted_execute.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/mounted_failure_scope.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/mounted_fusectl.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/mounted_install.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/mounted_links.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/mounted_listing_reads.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/mounted_low_water.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/mounted_parallel_commits.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/mounted_patterns.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/mounted_recognizer.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/mounted_rewind.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/mounted_serial_admission.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/mounted_sqlite_full.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/mounted_store_read.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/negative_entries.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/r5_10_producer_profile.rs (99%) rename {core => engine}/crates/layerfs-daemon/tests/r5_5_install_survival.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/r5_9_dirty_mapping.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/rename_predecessor.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/shared_cache_pressure.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/store_commit.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/store_reader_lifecycle.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/support/captured_drive.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/support/complete_bytes.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/support/complete_fixture.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/support/complete_oracle.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/support/control_fixture.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/support/delete_trace.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/support/fusectl.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/support/held_writer.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/support/history_boundary.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/support/history_gate.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/support/holds.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/support/host_install.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/support/install_docker.rs (97%) rename {core => engine}/crates/layerfs-daemon/tests/support/installed_store.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/support/long_branch_rig.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/support/mounted.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/support/mounted_commit.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/support/mutating.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/support/namespace_model.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/support/record_counts.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/support/request_path.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/support/request_path_counts/c01.txt (100%) rename {core => engine}/crates/layerfs-daemon/tests/support/request_path_counts/c03.txt (100%) rename {core => engine}/crates/layerfs-daemon/tests/support/request_path_counts/c04.txt (100%) rename {core => engine}/crates/layerfs-daemon/tests/support/request_path_counts/c06.txt (100%) rename {core => engine}/crates/layerfs-daemon/tests/support/request_path_counts/c10.txt (100%) rename {core => engine}/crates/layerfs-daemon/tests/support/shared_cache_rig.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/support/statement_trace.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/support/store_gate.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/telemetry_recording.rs (100%) rename {core => engine}/crates/layerfs-daemon/tests/workspace_databases.rs (100%) rename {core => engine}/crates/layerfs-fuse/Cargo.toml (88%) rename {core => engine}/crates/layerfs-fuse/src/attributes.rs (100%) rename {core => engine}/crates/layerfs-fuse/src/coherence/attributes.rs (100%) rename {core => engine}/crates/layerfs-fuse/src/coherence/mod.rs (100%) rename {core => engine}/crates/layerfs-fuse/src/coherence/pages.rs (100%) rename {core => engine}/crates/layerfs-fuse/src/coherence/reply_order.rs (100%) rename {core => engine}/crates/layerfs-fuse/src/dispatch/diagnostics.rs (100%) rename {core => engine}/crates/layerfs-fuse/src/dispatch/mod.rs (100%) rename {core => engine}/crates/layerfs-fuse/src/dispatch/requests.rs (100%) rename {core => engine}/crates/layerfs-fuse/src/dispatch/types.rs (100%) rename {core => engine}/crates/layerfs-fuse/src/lib.rs (100%) rename {core => engine}/crates/layerfs-fuse/src/mount/mod.rs (100%) rename {core => engine}/crates/layerfs-fuse/src/mount/profile.rs (100%) rename {core => engine}/crates/layerfs-fuse/src/mount/syscalls.rs (100%) rename {core => engine}/crates/layerfs-fuse/src/operations/create.rs (100%) rename {core => engine}/crates/layerfs-fuse/src/operations/directory.rs (100%) rename {core => engine}/crates/layerfs-fuse/src/operations/flush.rs (100%) rename {core => engine}/crates/layerfs-fuse/src/operations/link.rs (100%) rename {core => engine}/crates/layerfs-fuse/src/operations/lookup.rs (100%) rename {core => engine}/crates/layerfs-fuse/src/operations/mod.rs (100%) rename {core => engine}/crates/layerfs-fuse/src/operations/mutation.rs (100%) rename {core => engine}/crates/layerfs-fuse/src/operations/read.rs (100%) rename {core => engine}/crates/layerfs-fuse/src/operations/remove.rs (100%) rename {core => engine}/crates/layerfs-fuse/src/operations/rename.rs (100%) rename {core => engine}/crates/layerfs-fuse/src/operations/unsupported.rs (100%) rename {core => engine}/crates/layerfs-fuse/src/operations/write.rs (100%) rename {core => engine}/crates/layerfs-fuse/src/phase.rs (100%) rename {core => engine}/crates/layerfs-fuse/src/ports.rs (100%) rename {core => engine}/crates/layerfs-fuse/src/request/accounting.rs (100%) rename {core => engine}/crates/layerfs-fuse/src/request/callbacks.rs (100%) rename {core => engine}/crates/layerfs-fuse/src/request/directory.rs (100%) rename {core => engine}/crates/layerfs-fuse/src/request/failure.rs (100%) rename {core => engine}/crates/layerfs-fuse/src/request/inline.rs (100%) rename {core => engine}/crates/layerfs-fuse/src/request/mod.rs (100%) rename {core => engine}/crates/layerfs-fuse/src/request/mutate.rs (100%) rename {core => engine}/crates/layerfs-fuse/src/request/reply.rs (100%) rename {core => engine}/crates/layerfs-fuse/src/request/state.rs (100%) rename {core => engine}/crates/layerfs-fuse/src/request/terminal.rs (100%) rename {core => engine}/crates/layerfs-fuse/src/session/drain.rs (100%) rename {core => engine}/crates/layerfs-fuse/src/session/force.rs (100%) rename {core => engine}/crates/layerfs-fuse/src/session/invalidate.rs (100%) rename {core => engine}/crates/layerfs-fuse/src/session/mod.rs (100%) rename {core => engine}/crates/layerfs-fuse/src/session/startup.rs (100%) rename {core => engine}/crates/layerfs-fuse/src/session/state.rs (100%) rename {core => engine}/crates/layerfs-fuse/tests/attributes.rs (100%) rename {core => engine}/crates/layerfs-fuse/tests/opcode_names.rs (100%) rename {core => engine}/crates/layerfs-fuse/tests/opcode_time.rs (100%) rename {core => engine}/crates/layerfs-fuse/tests/requests.rs (100%) rename {core => engine}/crates/layerfs-overlay/Cargo.toml (100%) rename {core => engine}/crates/layerfs-overlay/examples/indexed_operation_record_profile.rs (100%) rename {core => engine}/crates/layerfs-overlay/sql/schema.sql (100%) rename {core => engine}/crates/layerfs-overlay/src/contract/custody.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/contract/error.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/contract/indexed_operation_record.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/contract/kernel.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/contract/kernel_directory.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/contract/mod.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/contract/types.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/database/accounting.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/database/connection.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/database/mod.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/database/physical.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/database/profile.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/database/startup.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/database/statements.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/diagnostics/indexed_operation_record_plan.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/diagnostics/metrics.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/diagnostics/mod.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/diagnostics/payload.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/diagnostics/startup.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/lib.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/lifetime/captured_reader.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/lifetime/close.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/lifetime/composition.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/lifetime/file_owners.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/lifetime/frontier.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/lifetime/generation.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/lifetime/indexed_operation_record.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/lifetime/kernel.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/lifetime/kernel_cookie.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/lifetime/kernel_directory.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/lifetime/kernel_directory_read.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/lifetime/kernel_file.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/lifetime/kernel_mutation.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/lifetime/kernel_visit.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/lifetime/lookup.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/lifetime/mod.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/lifetime/operation.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/lifetime/orphan.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/lifetime/source.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/lifetime/tickets.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/lifetime/workspace.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/maintenance/garbage.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/maintenance/indexed_operation_record.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/maintenance/mod.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/maintenance/orphan.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/maintenance/pieces.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/maintenance/ready.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/maintenance/source_wait.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/maintenance/work.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/namespace/captured_namespace.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/namespace/compound.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/namespace/directory_entry.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/namespace/inode.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/namespace/job_rows.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/namespace/mod.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/namespace/predecessor.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/open/counts.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/open/directories.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/open/files.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/open/journal.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/open/kernel.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/open/mod.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/payload/access.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/payload/captured_runs.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/payload/captured_types.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/payload/cells.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/payload/digest.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/payload/layers.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/payload/mod.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/payload/pieces/captured.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/payload/pieces/mod.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/payload/pieces/moves.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/payload/pieces/rows.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/payload/runs.rs (100%) rename {core => engine}/crates/layerfs-overlay/src/payload/stream.rs (100%) rename {core => engine}/crates/layerfs-overlay/tests/allocation_filesystem.rs (100%) rename {core => engine}/crates/layerfs-overlay/tests/captured_namespace.rs (100%) rename {core => engine}/crates/layerfs-overlay/tests/captured_runs.rs (100%) rename {core => engine}/crates/layerfs-overlay/tests/device_fixture.sh (86%) rename {core => engine}/crates/layerfs-overlay/tests/digests.rs (100%) rename {core => engine}/crates/layerfs-overlay/tests/enospc_as_eio.c (100%) rename {core => engine}/crates/layerfs-overlay/tests/error_identity.rs (100%) rename {core => engine}/crates/layerfs-overlay/tests/indexed_operation_record.rs (100%) rename {core => engine}/crates/layerfs-overlay/tests/indexed_operation_record_cursor.rs (100%) rename {core => engine}/crates/layerfs-overlay/tests/indexed_operation_record_entries.rs (100%) rename {core => engine}/crates/layerfs-overlay/tests/kept_live.rs (100%) rename {core => engine}/crates/layerfs-overlay/tests/kernel_memory.rs (100%) rename {core => engine}/crates/layerfs-overlay/tests/orphans.rs (100%) rename {core => engine}/crates/layerfs-overlay/tests/payload.rs (100%) rename {core => engine}/crates/layerfs-overlay/tests/payload_runs.rs (100%) rename {core => engine}/crates/layerfs-overlay/tests/payload_support/mod.rs (100%) rename {core => engine}/crates/layerfs-overlay/tests/piece_lifetimes.rs (100%) rename {core => engine}/crates/layerfs-overlay/tests/pieces.rs (100%) rename {core => engine}/crates/layerfs-persistence/Cargo.toml (72%) rename {core => engine}/crates/layerfs-persistence/README.md (100%) rename {core => engine}/crates/layerfs-persistence/examples/explain_reservation.rs (100%) rename {core => engine}/crates/layerfs-persistence/examples/issue327_counters_v2.rs (100%) rename {core => engine}/crates/layerfs-persistence/examples/issue327_counters_v3.rs (100%) rename {core => engine}/crates/layerfs-persistence/examples/issue327_counters_v4.rs (100%) rename {core => engine}/crates/layerfs-persistence/examples/issue327_counters_v5.rs (100%) rename {core => engine}/crates/layerfs-persistence/examples/issue327_readonly_diagnostic.rs (100%) rename {core => engine}/crates/layerfs-persistence/examples/metadata_allocation_probe.rs (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/acquisition/queries/abandoned.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/acquisition/queries/advance.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/acquisition/queries/begin.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/acquisition/queries/bind_host_file.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/acquisition/queries/bindings_first.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/acquisition/queries/bindings_next.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/acquisition/queries/charge.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/acquisition/queries/claim_epoch.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/acquisition/queries/complete_file.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/acquisition/queries/credit.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/acquisition/queries/directories.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/acquisition/queries/directory_path.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/acquisition/queries/directory_sizes.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/acquisition/queries/discard_entries.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/acquisition/queries/discard_entry_keys.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/acquisition/queries/discard_entry_tail.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/acquisition/queries/discard_host_file.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/acquisition/queries/discard_host_file_keys.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/acquisition/queries/discard_host_file_tail.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/acquisition/queries/entries_first.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/acquisition/queries/entries_next.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/acquisition/queries/entry_dependencies.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/acquisition/queries/file_roots.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/acquisition/queries/job.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/acquisition/queries/job_sizes.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/acquisition/queries/jobs.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/acquisition/queries/owner.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/acquisition/queries/place_entry.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/acquisition/queries/put_entries.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/acquisition/queries/put_entry.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/acquisition/queries/put_host_file.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/acquisition/queries/release.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/acquisition/queries/release_abandoned.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/acquisition/queries/set_directory_root.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/acquisition/queries/unplaced_first.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/acquisition/queries/unplaced_next.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/acquisition/schema.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/file_digest.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/history.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/lineage.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/merge_scratch.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/metadata.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/objects.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/objects_units.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/objects_units_index.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/queries/history/allocation_advance_scope.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/queries/history/allocation_insert_scope.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/queries/history/allocation_scope_by_id.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/queries/history/branch_branch_by_id.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/queries/history/branch_branch_by_name.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/queries/history/branch_branch_first_page.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/queries/history/branch_branch_name_taken.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/queries/history/branch_branch_next_page.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/queries/history/branch_insert_branch.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/queries/history/commit_advance_branch.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/queries/history/commit_commit_by_id.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/queries/history/commit_insert_commit.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/queries/history/digest_insert.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/queries/history/digest_of.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/queries/history/hint_bindings_of.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/queries/history/hint_insert_binding.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_advance_stack.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_insert_layer.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_insert_stack.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_layer_by_id.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_layer_by_source.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_layer_root.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_stack_by_id.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_stack_by_name.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_stack_first_page.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_stack_head.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_stack_name_taken.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_stack_next_page.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_absorb.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_absorbed_below.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_absorbed_height.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_commit.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_commit_at.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_insert_commit.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_insert_layer.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_layer.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_layers_above.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_merges.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_reach.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_reach_insert.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_reach_prune.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/queries/history/statistics_record_init.sql (100%) rename {core => engine}/crates/layerfs-persistence/sql/sqlite/queries/history/statistics_totals.sql (100%) rename {core => engine}/crates/layerfs-persistence/src/backend/mod.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/backend/records.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/backend/sqlite/acquisition/accounting.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/backend/sqlite/acquisition/cleanup.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/backend/sqlite/acquisition/entry_windows.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/backend/sqlite/acquisition/metadata.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/backend/sqlite/acquisition/mod.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/backend/sqlite/acquisition/reads.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/backend/sqlite/acquisition/root_windows.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/backend/sqlite/acquisition/statements.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/backend/sqlite/acquisition/writes.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/backend/sqlite/admission.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/backend/sqlite/connection.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/backend/sqlite/file_control.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/backend/sqlite/lane.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/backend/sqlite/metadata_allocation.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/backend/sqlite/metadata_locations.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/backend/sqlite/metadata_policy.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/backend/sqlite/metadata_signatures.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/backend/sqlite/metadata_values.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/backend/sqlite/mod.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/backend/sqlite/objects_read.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/backend/sqlite/objects_selection.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/backend/sqlite/prepared.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/backend/sqlite/profile.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/backend/sqlite/publish.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/backend/sqlite/query.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/backend/sqlite/reclamation.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/backend/sqlite/rows.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/backend/sqlite/schema.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/backend/sqlite/seal.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/backend/sqlite/seal_allocation.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/backend/sqlite/statement_work.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/backend/sqlite/thread_work.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/backend/sqlite/transaction.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/backend/sqlite/unit_io.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/backend/sqlite/unit_layout.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/backend/sqlite/units_publish.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/backend/sqlite/units_read.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/backend/sqlite/writer_admission.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/history/allocation.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/history/ancestry.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/history/bindings.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/history/branch.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/history/catalog.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/history/commit.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/history/digests.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/history/facts.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/history/hints.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/history/layerstack.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/history/lineage.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/history/lineage_backfill.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/history/merge.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/history/mod.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/history/provider.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/history/rows.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/history/transaction.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/lib.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/metadata/allocation.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/metadata/locations.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/metadata/mod.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/metadata/policy.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/metadata/signatures.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/metadata/values.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/objects/mod.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/objects/read.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/storage/acquisition/mod.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/storage/acquisition/provider.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/storage/merge_records.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/storage/mod.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/storage/provider.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/storage/publication.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/store/config.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/store/handles.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/store/mod.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/store/open.rs (100%) rename {core => engine}/crates/layerfs-persistence/src/store/seal.rs (100%) rename {core => engine}/crates/layerfs-persistence/tests/acquisition_batching.rs (100%) rename {core => engine}/crates/layerfs-persistence/tests/acquisition_disposal.rs (100%) rename {core => engine}/crates/layerfs-persistence/tests/acquisition_reads.rs (100%) rename {core => engine}/crates/layerfs-persistence/tests/concurrent_first_installs.rs (100%) rename {core => engine}/crates/layerfs-persistence/tests/concurrent_pooled_saves.rs (100%) rename {core => engine}/crates/layerfs-persistence/tests/diagnostics_during_lane.rs (100%) rename {core => engine}/crates/layerfs-persistence/tests/disposable_startup_sync.rs (100%) rename {core => engine}/crates/layerfs-persistence/tests/file_lengths.rs (100%) rename {core => engine}/crates/layerfs-persistence/tests/history_allocation.rs (100%) rename {core => engine}/crates/layerfs-persistence/tests/history_remediation.rs (100%) rename {core => engine}/crates/layerfs-persistence/tests/immutable_reads_under_reclamation.rs (100%) rename {core => engine}/crates/layerfs-persistence/tests/inode_branch_delta_custody.rs (100%) rename {core => engine}/crates/layerfs-persistence/tests/interleaved_saves.rs (100%) rename {core => engine}/crates/layerfs-persistence/tests/lineage_backfill.rs (100%) rename {core => engine}/crates/layerfs-persistence/tests/lineage_backfill_measure.rs (100%) rename {core => engine}/crates/layerfs-persistence/tests/merge_records.rs (100%) rename {core => engine}/crates/layerfs-persistence/tests/old_format_open.rs (100%) rename {core => engine}/crates/layerfs-persistence/tests/seal_allocation.rs (100%) rename {core => engine}/crates/layerfs-persistence/tests/semantic_admission.rs (100%) rename {core => engine}/crates/layerfs-persistence/tests/serverless_store.rs (100%) rename {core => engine}/crates/layerfs-persistence/tests/signature_ring_order.rs (100%) rename {core => engine}/crates/layerfs-persistence/tests/space_reclamation.rs (100%) rename {core => engine}/crates/layerfs-persistence/tests/sqlite_group_rows.rs (100%) rename {core => engine}/crates/layerfs-persistence/tests/sqlite_group_rows_indexed.rs (100%) rename {core => engine}/crates/layerfs-persistence/tests/sqlite_inode_values.rs (100%) rename {core => engine}/crates/layerfs-persistence/tests/sqlite_lock_custody.rs (100%) rename {core => engine}/crates/layerfs-persistence/tests/sqlite_ordinal_lookahead.rs (100%) rename {core => engine}/crates/layerfs-persistence/tests/sqlite_pack_selection.rs (100%) rename {core => engine}/crates/layerfs-persistence/tests/sqlite_publication.rs (100%) rename {core => engine}/crates/layerfs-persistence/tests/sqlite_recovery.rs (100%) rename {core => engine}/crates/layerfs-persistence/tests/sqlite_reference_acquisition.rs (100%) rename {core => engine}/crates/layerfs-persistence/tests/sqlite_transaction_units.rs (100%) rename {core => engine}/crates/layerfs-persistence/tests/support/mod.rs (100%) rename {core => engine}/crates/layerfs-persistence/tests/thread_work.rs (100%) rename {core => engine}/crates/layerfs-persistence/tests/writer_admission.rs (100%) rename {core => engine}/crates/layerfs-project/Cargo.toml (55%) rename {core => engine}/crates/layerfs-project/examples/acquisition_profile.rs (100%) rename {core => engine}/crates/layerfs-project/examples/benchmark_init.rs (100%) rename {core => engine}/crates/layerfs-project/examples/durable_init_costs.rs (100%) rename {core => engine}/crates/layerfs-project/examples/durable_init_costs/vfs.rs (100%) rename {core => engine}/crates/layerfs-project/examples/history_support/canonical_memo.rs (100%) rename {core => engine}/crates/layerfs-project/examples/verify_namespace.rs (100%) rename {core => engine}/crates/layerfs-project/src/import/backing.rs (100%) rename {core => engine}/crates/layerfs-project/src/import/batch.rs (100%) rename {core => engine}/crates/layerfs-project/src/import/error.rs (100%) rename {core => engine}/crates/layerfs-project/src/import/files.rs (100%) rename {core => engine}/crates/layerfs-project/src/import/hints.rs (100%) rename {core => engine}/crates/layerfs-project/src/import/init.rs (100%) rename {core => engine}/crates/layerfs-project/src/import/mod.rs (100%) rename {core => engine}/crates/layerfs-project/src/import/namespace.rs (100%) rename {core => engine}/crates/layerfs-project/src/import/observe.rs (100%) rename {core => engine}/crates/layerfs-project/src/import/scan.rs (100%) rename {core => engine}/crates/layerfs-project/src/import/source.rs (100%) rename {core => engine}/crates/layerfs-project/src/import/work.rs (100%) rename {core => engine}/crates/layerfs-project/src/lib.rs (100%) rename {core => engine}/crates/layerfs-project/src/store/init.rs (100%) rename {core => engine}/crates/layerfs-project/src/store/install.rs (100%) rename {core => engine}/crates/layerfs-project/src/store/install_types.rs (100%) rename {core => engine}/crates/layerfs-project/src/store/mod.rs (100%) rename {core => engine}/crates/layerfs-project/tests/acquisition_custody.rs (100%) rename {core => engine}/crates/layerfs-project/tests/backed_acquisition.rs (100%) rename {core => engine}/crates/layerfs-project/tests/complete_root.rs (100%) rename {core => engine}/crates/layerfs-project/tests/history_proof_memo.rs (100%) rename {core => engine}/crates/layerfs-project/tests/init_counters.rs (100%) rename {core => engine}/crates/layerfs-project/tests/init_memory.rs (100%) rename {core => engine}/crates/layerfs-project/tests/init_sqlite.rs (100%) rename {core => engine}/crates/layerfs-project/tests/namespace_scaling.rs (100%) rename {core => engine}/crates/layerfs-project/tests/support/memory_acquisition.rs (100%) rename {core => engine}/crates/layerfs-project/tests/support/memory_history.rs (100%) rename {core => engine}/crates/layerfs-project/tests/support/memory_objects.rs (100%) rename {core => engine}/crates/layerfs-project/tests/support/mod.rs (98%) rename {core => engine}/crates/layerfs-project/tests/support/old_snapshot.rs (100%) rename {core => engine}/crates/layerfs-sandbox/Cargo.toml (100%) rename {core => engine}/crates/layerfs-sandbox/examples/engine_streams.rs (100%) rename {core => engine}/crates/layerfs-sandbox/src/backend/docker/archive.rs (100%) rename {core => engine}/crates/layerfs-sandbox/src/backend/docker/body.rs (100%) rename {core => engine}/crates/layerfs-sandbox/src/backend/docker/container.rs (100%) rename {core => engine}/crates/layerfs-sandbox/src/backend/docker/container_types.rs (100%) rename {core => engine}/crates/layerfs-sandbox/src/backend/docker/endpoint.rs (100%) rename {core => engine}/crates/layerfs-sandbox/src/backend/docker/headers.rs (100%) rename {core => engine}/crates/layerfs-sandbox/src/backend/docker/http.rs (100%) rename {core => engine}/crates/layerfs-sandbox/src/backend/docker/inspect.rs (100%) rename {core => engine}/crates/layerfs-sandbox/src/backend/docker/json.rs (100%) rename {core => engine}/crates/layerfs-sandbox/src/backend/docker/listener.rs (100%) rename {core => engine}/crates/layerfs-sandbox/src/backend/docker/mod.rs (100%) rename {core => engine}/crates/layerfs-sandbox/src/backend/docker/mux.rs (100%) rename {core => engine}/crates/layerfs-sandbox/src/backend/docker/request.rs (100%) rename {core => engine}/crates/layerfs-sandbox/src/backend/docker/socket.rs (100%) rename {core => engine}/crates/layerfs-sandbox/src/backend/docker/streams.rs (100%) rename {core => engine}/crates/layerfs-sandbox/src/backend/docker/strings.rs (100%) rename {core => engine}/crates/layerfs-sandbox/src/backend/docker/topology.rs (100%) rename {core => engine}/crates/layerfs-sandbox/src/backend/mod.rs (100%) rename {core => engine}/crates/layerfs-sandbox/src/lib.rs (100%) rename {core => engine}/crates/layerfs-sandbox/src/types/execution.rs (100%) rename {core => engine}/crates/layerfs-sandbox/src/types/failure.rs (100%) rename {core => engine}/crates/layerfs-sandbox/src/types/identity.rs (100%) rename {core => engine}/crates/layerfs-sandbox/src/types/mod.rs (100%) rename {core => engine}/crates/layerfs-sandbox/src/types/transfer.rs (100%) rename {core => engine}/crates/layerfs-sandbox/tests/container_labels.rs (100%) rename {core => engine}/crates/layerfs-sandbox/tests/docker_naming.rs (100%) rename {core => engine}/crates/layerfs-sandbox/tests/engine_keepalive.rs (100%) rename {core => engine}/crates/layerfs-sandbox/tests/engine_lifecycle.rs (100%) rename {core => engine}/crates/layerfs-sandbox/tests/engine_protocol.rs (100%) rename {core => engine}/crates/layerfs-sandbox/tests/support/engine.rs (100%) rename {core => engine}/crates/layerfs-store-service/Cargo.toml (72%) rename {core => engine}/crates/layerfs-store-service/src/bootstrap.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/history/branch.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/history/lookup.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/history/mod.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/history/units.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/install.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/kernel_guard.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/lib.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/operator/args.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/operator/dispatch.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/operator/files.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/operator/inspect.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/operator/mod.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/operator/store.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/overlay/backing.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/overlay/captured_namespace_port.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/overlay/captured_run_port.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/overlay/file_port.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/overlay/kernel_operations.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/overlay/lifetime_operations.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/overlay/mod.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/overlay/operation_record_port.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/overlay/owner.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/overlay/read_operations.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/overlay/read_port.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/overlay/scopes.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/overlay/state.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/overlay/workspaces.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/read/blame.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/read/cached.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/read/compare.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/read/mod.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/read/plans.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/read/reads.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/read/search.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/read/snapshot.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/read/walk.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/read/window.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/service/mod.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/service/observations.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/service/owner_work.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/service/results.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/service/startup.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/store/bind.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/store/captured.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/store/commit.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/store/commit_merge.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/store/commit_types.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/store/digests.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/store/hints.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/store/mod.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/store/open.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/store/operation.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/store/ports.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/store/producer.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/store/read_handle.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/store/read_service.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/store/recognizer.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/store/settle.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/store/statistics.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/store/types.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/store_service.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/telemetry.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/write/edit.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/write/files.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/write/mod.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/write/mutation.rs (100%) rename {core => engine}/crates/layerfs-store-service/src/write/recursive.rs (100%) rename {core => engine}/crates/layerfs-store-service/tests/kept_plans.rs (100%) rename {core => engine}/crates/layerfs-store-service/tests/kernel_guard.rs (100%) rename {core => engine}/crates/layerfs-store-service/tests/sdk_root_batches.rs (100%) rename {core => engine}/crates/layerfs-workspace/Cargo.toml (72%) rename {core => engine}/crates/layerfs-workspace/src/base/cache.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/base/client.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/base/file.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/base/links.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/base/mod.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/base/view.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/construction/captured/context.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/construction/captured/edges.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/construction/captured/mod.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/construction/captured/normalize.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/construction/captured/owner.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/construction/captured/scan.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/construction/captured/script.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/construction/captured/source.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/construction/captured/state.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/construction/driver.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/construction/mod.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/construction/namespace/cursor.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/construction/namespace/inodes.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/construction/namespace/mod.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/construction/namespace/normalize.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/construction/namespace/records.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/construction/outcome.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/construction/records.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/lib.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/mutation/driver.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/mutation/eval.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/mutation/facts.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/mutation/job.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/mutation/mod.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/mutation/plan.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/operations/attributes.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/operations/file/mod.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/operations/file/read.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/operations/file/recognize.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/operations/file/write.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/operations/kernel_data.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/operations/kernel_directory.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/operations/kernel_mutation.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/operations/kernel_read.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/operations/kernel_visit.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/operations/mod.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/operations/namespace/create.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/operations/namespace/list.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/operations/namespace/mod.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/operations/namespace/remove.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/operations/namespace/rename.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/operations/types.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/ports/captured_namespace.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/ports/captured_runs.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/ports/digests.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/ports/files.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/ports/lengths.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/ports/mod.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/ports/operation_record.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/ports/overlay.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/workspace/install.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/workspace/mod.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/workspace/route.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/workspace/serials.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/workspace/state.rs (100%) rename {core => engine}/crates/layerfs-workspace/src/workspace/view.rs (100%) rename {core => engine}/crates/layerfs-workspace/tests/captured_file_edits.rs (100%) rename {core => engine}/crates/layerfs-workspace/tests/captured_namespace.rs (100%) rename {core => engine}/crates/layerfs-workspace/tests/captured_namespace_cursor.rs (100%) rename {core => engine}/crates/layerfs-workspace/tests/captured_namespace_custody.rs (100%) rename {core => engine}/crates/layerfs-workspace/tests/captured_namespace_fragments.rs (100%) rename {core => engine}/crates/layerfs-workspace/tests/captured_namespace_holds.rs (100%) rename {core => engine}/crates/layerfs-workspace/tests/captured_namespace_inline.rs (100%) rename {core => engine}/crates/layerfs-workspace/tests/captured_namespace_metadata.rs (100%) rename {core => engine}/crates/layerfs-workspace/tests/captured_namespace_order.rs (100%) rename {core => engine}/crates/layerfs-workspace/tests/captured_namespace_perturbed.rs (100%) rename {core => engine}/crates/layerfs-workspace/tests/captured_namespace_rebound.rs (100%) rename {core => engine}/crates/layerfs-workspace/tests/captured_namespace_states.rs (100%) rename {core => engine}/crates/layerfs-workspace/tests/captured_new_file_route.rs (100%) rename {core => engine}/crates/layerfs-workspace/tests/captured_piece_edits.rs (100%) rename {core => engine}/crates/layerfs-workspace/tests/captured_support/mod.rs (100%) rename {core => engine}/crates/layerfs-workspace/tests/common/mod.rs (100%) rename {core => engine}/crates/layerfs-workspace/tests/decoded_pages.rs (100%) rename {core => engine}/crates/layerfs-workspace/tests/directory_links.rs (100%) rename {core => engine}/crates/layerfs-workspace/tests/directory_links_install.rs (100%) rename {core => engine}/crates/layerfs-workspace/tests/file_lengths.rs (100%) rename {core => engine}/crates/layerfs-workspace/tests/harness/mod.rs (100%) rename {core => engine}/crates/layerfs-workspace/tests/kernel_data.rs (100%) rename {core => engine}/crates/layerfs-workspace/tests/kernel_directory.rs (100%) rename {core => engine}/crates/layerfs-workspace/tests/kernel_visit.rs (100%) rename {core => engine}/crates/layerfs-workspace/tests/mutation_plan.rs (100%) rename {core => engine}/crates/layerfs-workspace/tests/namespace.rs (100%) rename {core => engine}/crates/layerfs-workspace/tests/namespace_view.rs (100%) rename {core => engine}/crates/layerfs-workspace/tests/nonfile.rs (100%) rename {core => engine}/crates/layerfs-workspace/tests/operation_scope.rs (100%) rename {core => engine}/crates/layerfs-workspace/tests/oracle/mod.rs (100%) rename {core => engine}/crates/layerfs-workspace/tests/payload.rs (100%) rename {core => engine}/crates/layerfs-workspace/tests/producer/mod.rs (100%) rename {core => engine}/crates/layerfs-workspace/tests/recognize.rs (100%) rename {core => engine}/crates/layerfs-workspace/tests/shared_cache_client.rs (100%) rename {core => engine}/crates/layerfs-workspace/tests/sibling_lengths.rs (100%) rename {core => engine}/patches/fuser-0.18.0/README.md (100%) rename {core => engine}/patches/fuser-0.18.0/lifecycle-provenance.json (100%) rename {core => engine}/patches/fuser-0.18.0/provenance.json (100%) rename {core => engine}/patches/fuser-0.18.0/receive-buffer-provenance.json (100%) rename {core => engine}/patches/fuser-0.18.0/receive-buffer.patch (100%) rename {core => engine}/patches/fuser-0.18.0/session-lifecycle.patch (100%) rename {core => engine}/patches/fuser-0.18.0/signed-timestamps.patch (100%) rename {core => engine}/vendor/fuser-0.18.0/.cargo_vcs_info.json (100%) rename {core => engine}/vendor/fuser-0.18.0/.dockerignore (100%) rename {core => engine}/vendor/fuser-0.18.0/.github/workflows/ci.yml (100%) rename {core => engine}/vendor/fuser-0.18.0/.gitignore (100%) rename {core => engine}/vendor/fuser-0.18.0/AGENTS.md (100%) rename {core => engine}/vendor/fuser-0.18.0/CHANGELOG.md (100%) rename {core => engine}/vendor/fuser-0.18.0/CLAUDE.md (100%) rename {core => engine}/vendor/fuser-0.18.0/Cargo.lock (100%) rename {core => engine}/vendor/fuser-0.18.0/Cargo.toml (100%) rename {core => engine}/vendor/fuser-0.18.0/Cargo.toml.orig (100%) rename {core => engine}/vendor/fuser-0.18.0/LICENSE.md (100%) rename {core => engine}/vendor/fuser-0.18.0/Makefile (100%) rename {core => engine}/vendor/fuser-0.18.0/README.md (100%) rename {core => engine}/vendor/fuser-0.18.0/build.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/deny.toml (100%) rename {core => engine}/vendor/fuser-0.18.0/examples/async_hello.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/examples/common/args.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/examples/common/mod.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/examples/hello.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/examples/ioctl.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/examples/notify_inval_entry.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/examples/notify_inval_inode.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/examples/null.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/examples/passthrough.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/examples/passthrough_fork.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/examples/poll.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/examples/poll_client.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/examples/simple.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/mount_tests_libfuse2.Dockerfile (100%) rename {core => engine}/vendor/fuser-0.18.0/mount_tests_libfuse3.Dockerfile (100%) rename {core => engine}/vendor/fuser-0.18.0/pjdfs.Dockerfile (100%) rename {core => engine}/vendor/fuser-0.18.0/pjdfs.sh (100%) rename {core => engine}/vendor/fuser-0.18.0/rust-toolchain (100%) rename {core => engine}/vendor/fuser-0.18.0/rustfmt.toml (100%) rename {core => engine}/vendor/fuser-0.18.0/src/access_flags.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/src/bsd_file_flags.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/src/channel.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/src/dev_fuse.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/src/experimental.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/src/forget_one.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/src/lib.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/src/ll/argument.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/src/ll/flags/copy_file_range_flags.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/src/ll/flags/cuse_init_flags.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/src/ll/flags/fattr_flags.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/src/ll/flags/fopen_flags.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/src/ll/flags/fsync_flags.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/src/ll/flags/getattr_flags.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/src/ll/flags/init_flags.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/src/ll/flags/ioctl_flags.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/src/ll/flags/mod.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/src/ll/flags/poll_flags.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/src/ll/flags/read_flags.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/src/ll/flags/release_flags.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/src/ll/flags/write_flags.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/src/ll/fuse_abi.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/src/ll/ioctl.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/src/ll/ioslice_concat.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/src/ll/mod.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/src/ll/notify.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/src/ll/reply.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/src/ll/request.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/src/mnt/fuse2.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/src/mnt/fuse2_sys.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/src/mnt/fuse3.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/src/mnt/fuse3_sys.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/src/mnt/fuse_pure.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/src/mnt/mod.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/src/mnt/mount_options.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/src/notify.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/src/open_flags.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/src/passthrough.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/src/poll_events.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/src/read_buf.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/src/rename_flags.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/src/reply.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/src/request.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/src/request_param.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/src/session.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/src/session/lifecycle.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/src/time.rs (100%) rename {core => engine}/vendor/fuser-0.18.0/tests/bsd_pjdfs.sh (100%) rename {core => engine}/vendor/fuser-0.18.0/tests/macos_pjdfs.sh (100%) rename {core => engine}/vendor/fuser-0.18.0/tests/test_passthrough.sh (100%) rename {core => engine}/vendor/fuser-0.18.0/xfstests.Dockerfile (100%) rename {core => engine}/vendor/fuser-0.18.0/xfstests.sh (100%) rename {core/tools => tools}/check_fuser_integrity.py (98%) rename {core/tools => tools}/check_product_boundary.py (92%) rename {core/tools => tools}/ci_tests.py (97%) rename {core/tools => tools}/phase7_services.py (99%) rename {core/tools => tools}/sdk_telemetry_report.py (100%) rename {core/tools => tools}/substitution-proof/README.md (100%) rename {core/tools => tools}/substitution-proof/arms/baseline/Cargo.lock (100%) rename {core/tools => tools}/substitution-proof/arms/baseline/Cargo.toml (100%) rename {core/tools => tools}/substitution-proof/arms/c1-only/Cargo.lock (100%) rename {core/tools => tools}/substitution-proof/arms/c1-only/Cargo.toml (100%) rename {core/tools => tools}/substitution-proof/arms/c2-only/Cargo.lock (100%) rename {core/tools => tools}/substitution-proof/arms/c2-only/Cargo.toml (100%) rename {core/tools => tools}/substitution-proof/arms/combined/Cargo.lock (100%) rename {core/tools => tools}/substitution-proof/arms/combined/Cargo.toml (100%) rename {core/tools => tools}/substitution-proof/consumer/core_pipeline.rs (100%) rename {core/tools => tools}/substitution-proof/consumer/cross_revision.rs (100%) rename {core/tools => tools}/substitution-proof/consumer/filesystem_primitives_candidate.rs (100%) rename {core/tools => tools}/substitution-proof/consumer/support/filesystem.rs (100%) rename {core/tools => tools}/substitution-proof/consumer/support/mod.rs (100%) rename {core/tools => tools}/substitution-proof/matrix.json (100%) rename {core/tools => tools}/substitution-proof/run.py (94%) rename {core/tools => tools}/test_check_fuser_integrity.py (97%) rename {core/tools => tools}/test_check_product_boundary.py (90%) rename {core/tools => tools}/test_ci_tests.py (94%) rename {core/tools => tools}/test_phase7_services.py (100%) rename {core/tools => tools}/test_sdk_telemetry_report.py (100%) diff --git a/.cargo/config.toml b/.cargo/config.toml index b32b8985e..97d75bd96 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -3,7 +3,7 @@ # This file sits at the repository root, not under `core/`, because cargo # discovers `.cargo/config.toml` by walking up from the **current working # directory**. The repository's prescribed commands run from this root with -# `--manifest-path core/Cargo.toml`, which never looks inside `core/.cargo/`, so +# the root manifest; a manifest path never selects a nested `.cargo/`, so # the flags used to be silently absent from exactly the builds that matter. # It is scoped by target cfg, so x86_64 and every other target are untouched. # @@ -18,7 +18,7 @@ # # Measured consequence of losing them (same source, same machine, same protocol): # 214 MiB/s against 802 MiB/s on one stream, 425 against 1556 MiB/s on two. -# `core/crates/layerfs-bridge` now refuses to compile for aarch64 without this +# `engine/crates/layerfs-bridge` now refuses to compile for aarch64 without this # profile instead of silently negotiating the ChaCha20-Poly1305 fallback. # # These are the crates' own documented cfg knobs plus the ARMv8 target features, @@ -26,7 +26,7 @@ # a scripted or container build that sets RUSTFLAGS must repeat these flags. # # The reference workspace that lived under root `crates/` was retired by R9c -# (2026-10-10); `core/` is the only Cargo workspace these flags apply to. +# (2026-10-10); the root workspace now covers core, engine and api. [target.'cfg(target_arch = "aarch64")'] rustflags = [ "--cfg", "aes_armv8", diff --git a/core/.config/nextest.toml b/.config/nextest.toml similarity index 85% rename from core/.config/nextest.toml rename to .config/nextest.toml index 3f29be483..361cb7b9b 100644 --- a/core/.config/nextest.toml +++ b/.config/nextest.toml @@ -1,5 +1,5 @@ # nextest profiles for the non-blocking GitHub CI. Selection lives in -# core/tools/ci_tests.py; this file only sets how a selected test runs. +# tools/ci_tests.py; this file only sets how a selected test runs. [profile.ci] # Every test is its own process. Report all failures; never retry one. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0aca57d06..46e35450f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,8 +1,9 @@ # Fast lane: runs after a push and reports. It is never a required check and # never blocks a push or merge; agents do not wait for it (AGENTS.md §4). -# Slow and FUSE mount tests run in nightly.yml. Selection: core/tools/ci_tests.py. -# The JavaScript API (api/, binding crate layerfs-node) is left out of CI (owner, -# 2026-10-23): no path trigger, excluded from Clippy and tests, skipped by the guard. +# Slow and FUSE mount tests run in nightly.yml. Selection: tools/ci_tests.py. +# The Node binding and JavaScript packages stay outside CI (owner, 2026-10-23): +# no path trigger, excluded from Clippy/tests and skipped by the guard. +# The Rust layerfs-api crate remains included at its relocated path. name: ci on: @@ -10,6 +11,11 @@ on: branches: [main] paths: - "core/**" + - "engine/**" + - "api/layerfs-api/**" + - "Cargo.*" + - ".config/**" + - "tools/**" - ".cargo/**" - ".github/workflows/ci.yml" - "!**/*.md" @@ -17,6 +23,11 @@ on: pull_request: paths: - "core/**" + - "engine/**" + - "api/layerfs-api/**" + - "Cargo.*" + - ".config/**" + - "tools/**" - ".cargo/**" - ".github/workflows/ci.yml" - "!**/*.md" @@ -44,14 +55,14 @@ jobs: steps: - uses: actions/checkout@v7.0.1 - run: rustup toolchain install 1.85.1 --profile minimal --component rustfmt - - run: cargo +1.85.1 fmt --manifest-path core/Cargo.toml --all -- --check + - run: cargo +1.85.1 fmt --manifest-path Cargo.toml --all -- --check # Each check reports even when an earlier one failed. - if: ${{ !cancelled() }} - run: python3 -B core/tools/check_product_boundary.py --skip-sdk + run: python3 -B tools/check_product_boundary.py --skip-sdk - if: ${{ !cancelled() }} - run: python3 -B core/tools/check_fuser_integrity.py + run: python3 -B tools/check_fuser_integrity.py - if: ${{ !cancelled() }} - run: python3 -B -m unittest discover -s core/tools -p 'test_*.py' + run: python3 -B -m unittest discover -s tools -p 'test_*.py' clippy: runs-on: ubuntu-24.04 @@ -61,9 +72,9 @@ jobs: - run: rustup toolchain install 1.85.1 --profile minimal --component clippy - uses: Swatinem/rust-cache@v2.9.2 with: - workspaces: core -> target + workspaces: . -> target save-if: ${{ github.ref == 'refs/heads/main' }} - - run: cargo +1.85.1 clippy --manifest-path core/Cargo.toml --locked --workspace --exclude layerfs-node --all-targets -- -D warnings + - run: cargo +1.85.1 clippy --manifest-path Cargo.toml --locked --workspace --exclude layerfs-node --all-targets -- -D warnings test: runs-on: ubuntu-24.04 @@ -85,7 +96,7 @@ jobs: tool: cargo-nextest@0.9.146 - uses: Swatinem/rust-cache@v2.9.2 with: - workspaces: core -> target + workspaces: . -> target save-if: ${{ github.ref == 'refs/heads/main' }} # Build first so compile time is never counted against the test ceiling. # Only the fast lane's test targets are built (one --test per name), since @@ -94,21 +105,21 @@ jobs: # no tests). --timings writes where build time goes, per unit. - name: Build test binaries run: | - targets="$(python3 -B core/tools/ci_tests.py targets fast)" + targets="$(python3 -B tools/ci_tests.py targets fast)" # shellcheck disable=SC2086 # one --test flag per word - cargo +1.85.1 test --manifest-path core/Cargo.toml --locked \ + cargo +1.85.1 test --manifest-path Cargo.toml --locked \ --workspace --exclude layerfs-node $targets --no-run --timings - name: Upload build timings if: ${{ !cancelled() }} uses: actions/upload-artifact@v7.0.2 with: name: test-build-timings - path: core/target/cargo-timings/cargo-timing.html + path: target/cargo-timings/cargo-timing.html retention-days: 14 - name: Run fast tests (whole run capped at 120 s) run: | - targets="$(python3 -B core/tools/ci_tests.py targets fast)" - filter="$(python3 -B core/tools/ci_tests.py filter fast)" + targets="$(python3 -B tools/ci_tests.py targets fast)" + filter="$(python3 -B tools/ci_tests.py filter fast)" # shellcheck disable=SC2086 # one --test flag per word - timeout 120 cargo +1.85.1 nextest run --manifest-path core/Cargo.toml --locked \ + timeout 120 cargo +1.85.1 nextest run --manifest-path Cargo.toml --locked \ --workspace --exclude layerfs-node $targets --profile ci -E "$filter" diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml index fc9016873..a393584bd 100644 --- a/.github/workflows/format.yml +++ b/.github/workflows/format.yml @@ -8,13 +8,11 @@ on: push: branches: [main] paths: - - "core/tools/**/*.py" - "tools/**/*.py" - "ruff.toml" - ".github/workflows/format.yml" pull_request: paths: - - "core/tools/**/*.py" - "tools/**/*.py" - "ruff.toml" - ".github/workflows/format.yml" diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index b7e57daf9..1bb0c27d9 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -1,5 +1,5 @@ # Nightly lane: the tests the fast lane leaves out. Report only; never a -# required check. Selection: core/tools/ci_tests.py. +# required check. Selection: tools/ci_tests.py. # - slow: binaries that take 5 s or more to run, plus the "heavy" ones that # take 5 s or more of build CPU (left out of the push job), on the # runner @@ -38,19 +38,19 @@ jobs: tool: cargo-nextest@0.9.146 - uses: Swatinem/rust-cache@v2.9.2 with: - workspaces: core -> target + workspaces: . -> target - name: Build test binaries run: | - targets="$(python3 -B core/tools/ci_tests.py targets nightly)" + targets="$(python3 -B tools/ci_tests.py targets nightly)" # shellcheck disable=SC2086 # one --test flag per word - cargo +1.85.1 test --manifest-path core/Cargo.toml --locked \ + cargo +1.85.1 test --manifest-path Cargo.toml --locked \ --workspace --exclude layerfs-node $targets --no-run - name: Run slow and heavy tests (whole run capped at 120 s) run: | - targets="$(python3 -B core/tools/ci_tests.py targets nightly)" - filter="$(python3 -B core/tools/ci_tests.py filter nightly)" + targets="$(python3 -B tools/ci_tests.py targets nightly)" + filter="$(python3 -B tools/ci_tests.py filter nightly)" # shellcheck disable=SC2086 # one --test flag per word - timeout 120 cargo +1.85.1 nextest run --manifest-path core/Cargo.toml --locked \ + timeout 120 cargo +1.85.1 nextest run --manifest-path Cargo.toml --locked \ --workspace --exclude layerfs-node $targets --profile ci -E "$filter" mount: @@ -61,14 +61,14 @@ jobs: - run: rustup toolchain install 1.85.1 --profile minimal - uses: Swatinem/rust-cache@v2.9.2 with: - workspaces: core -> target + workspaces: . -> target - name: Build mount test binaries run: | - targets="$(python3 -B core/tools/ci_tests.py mount-targets)" + targets="$(python3 -B tools/ci_tests.py mount-targets)" # shellcheck disable=SC2086 # one --test flag per word - cargo +1.85.1 test --manifest-path core/Cargo.toml --locked -p layerfs-daemon -p layerfs-api \ + cargo +1.85.1 test --manifest-path Cargo.toml --locked -p layerfs-daemon -p layerfs-api \ $targets --no-run --message-format json > "$RUNNER_TEMP/build.json" - python3 -B core/tools/ci_tests.py executables < "$RUNNER_TEMP/build.json" > "$RUNNER_TEMP/mount.tsv" + python3 -B tools/ci_tests.py executables < "$RUNNER_TEMP/build.json" > "$RUNNER_TEMP/mount.tsv" test -s "$RUNNER_TEMP/mount.tsv" wc -l < "$RUNNER_TEMP/mount.tsv" - name: Prepare FUSE and the test image diff --git a/.gitignore b/.gitignore index bbc299ea0..6d259e61e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ target/ -/core/target-linux/ +/target-linux/ /eval/runs/ /eval/datasets/ .DS_Store diff --git a/core/Cargo.lock b/Cargo.lock similarity index 100% rename from core/Cargo.lock rename to Cargo.lock diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 000000000..a5ce75470 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,31 @@ +# LayerFS workspace: core algorithms, engine composition and public API. + +[workspace] +resolver = "2" +members = [ + "core/crates/*", + "engine/crates/*", + "api/layerfs-api", + "api/binding", +] +exclude = [ + "engine/vendor/fuser-0.18.0", +] + +[workspace.package] +edition = "2021" +version = "1.1.0" +rust-version = "1.85" +license = "MIT" + +# Keep the large boundary fixtures cheap without removing cases or assertions. +# Product dev/release profiles and test debug assertions stay unchanged. +[profile.test] +opt-level = 1 + +[profile.test.package.zstd-sys] +opt-level = 3 + +# Owner-authorized signed-timestamp correction to the crates.io 0.18.0 archive. +[patch.crates-io] +fuser = { version = "=0.18.0", path = "engine/vendor/fuser-0.18.0" } diff --git a/api/agent/sdk/test/verify/direct_refusal_real.mjs b/api/agent/sdk/test/verify/direct_refusal_real.mjs index 6edc6d036..71efdf2e1 100644 --- a/api/agent/sdk/test/verify/direct_refusal_real.mjs +++ b/api/agent/sdk/test/verify/direct_refusal_real.mjs @@ -4,7 +4,7 @@ // (Docker Desktop's shared filesystem) and on tmpfs are each refused // `Unsupported` before any write: the file's bytes are unchanged and no // overlay directory is left. macOS is covered by -// core/crates/layerfs-store-service/tests/kernel_guard.rs. +// engine/crates/layerfs-store-service/tests/kernel_guard.rs. // // node api/agent/sdk/test/verify/direct_refusal_real.mjs outer import assert from "node:assert/strict"; @@ -53,7 +53,7 @@ function outer([daemon, addon, image]) { assert.ok(daemon && addon && image, "usage: outer "); const stamp = `f020-refusal-${Date.now().toString(36)}`; const volume = `layerfs-issue352-${stamp}`; - const bound = join(REPO, "core/target/f020", stamp); + const bound = join(REPO, "target/f020", stamp); mkdirSync(bound, { recursive: true }); execFileSync("docker", ["volume", "create", volume], { stdio: "ignore" }); let run; diff --git a/api/agent/sdk/test/verify/exec_mount_lookup_real.mjs b/api/agent/sdk/test/verify/exec_mount_lookup_real.mjs index 31076d6e6..0ddaefcdc 100644 --- a/api/agent/sdk/test/verify/exec_mount_lookup_real.mjs +++ b/api/agent/sdk/test/verify/exec_mount_lookup_real.mjs @@ -101,7 +101,7 @@ function outer([daemon, addon, image]) { assert.ok(daemon && addon && image, "usage: outer "); const stamp = `f029-${Date.now().toString(36)}`; const volume = `layerfs-issue352-${stamp}`; - const home = join(REPO, "core/target/f009", `${stamp}-home`); + const home = join(REPO, "target/f009", `${stamp}-home`); mkdirSync(home, { recursive: true }); chmodSync(home, 0o700); // LAYERFS_HOME must be private let r; diff --git a/api/agent/sdk/test/verify/exec_output_real.mjs b/api/agent/sdk/test/verify/exec_output_real.mjs index 04cec6df7..f2ddb63d8 100644 --- a/api/agent/sdk/test/verify/exec_output_real.mjs +++ b/api/agent/sdk/test/verify/exec_output_real.mjs @@ -145,7 +145,7 @@ function outer([daemon, addon, image, phase = "check"]) { assert.ok(daemon && addon && image, "usage: outer [check|time]"); const stamp = `f056-${Date.now().toString(36)}`; const volume = `layerfs-issue352-${stamp}`; - const home = join(REPO, "core/target/f056", `${stamp}-home`); + const home = join(REPO, "target/f056", `${stamp}-home`); mkdirSync(home, { recursive: true }); chmodSync(home, 0o700); // LAYERFS_HOME must be private let r; diff --git a/api/agent/sdk/test/verify/reap_real.mjs b/api/agent/sdk/test/verify/reap_real.mjs index 484164631..ac80c318b 100644 --- a/api/agent/sdk/test/verify/reap_real.mjs +++ b/api/agent/sdk/test/verify/reap_real.mjs @@ -50,7 +50,7 @@ function outer([daemon, addon, image]) { assert.ok(daemon && addon && image, "usage: outer "); const stamp = `reap-${Date.now().toString(36)}`; const volume = `layerfs-issue352-${stamp}`; - const home = join(REPO, "core/target/f054", `${stamp}-home`); + const home = join(REPO, "target/f054", `${stamp}-home`); mkdirSync(home, { recursive: true }); chmodSync(home, 0o700); // LAYERFS_HOME must be private let r; diff --git a/api/binding/Cargo.toml b/api/binding/Cargo.toml index b24ba4df1..407396582 100644 --- a/api/binding/Cargo.toml +++ b/api/binding/Cargo.toml @@ -2,7 +2,7 @@ name = "layerfs-node" description = "Node binding for the LayerFS JavaScript SDK: Store calls in-process (layerfs-store-service), Sandbox calls over layerfs-api" publish = false -workspace = "../../core" +workspace = "../.." edition.workspace = true version.workspace = true rust-version.workspace = true @@ -13,14 +13,14 @@ crate-type = ["cdylib"] path = "src/lib.rs" [dependencies] -layerfs-project = { path = "../../core/crates/layerfs-project" } -layerfs-api = { path = "../../core/crates/layerfs-api" } -layerfs-bridge = { path = "../../core/crates/layerfs-bridge" } +layerfs-project = { path = "../../engine/crates/layerfs-project" } +layerfs-api = { path = "../layerfs-api" } +layerfs-bridge = { path = "../../engine/crates/layerfs-bridge" } layerfs-history = { path = "../../core/crates/layerfs-history" } -layerfs-persistence = { path = "../../core/crates/layerfs-persistence" } -layerfs-sandbox = { path = "../../core/crates/layerfs-sandbox" } +layerfs-persistence = { path = "../../engine/crates/layerfs-persistence" } +layerfs-sandbox = { path = "../../engine/crates/layerfs-sandbox" } layerfs-storage = { path = "../../core/crates/layerfs-storage" } -layerfs-store-service = { path = "../../core/crates/layerfs-store-service" } +layerfs-store-service = { path = "../../engine/crates/layerfs-store-service" } layerfs-telemetry = { path = "../../core/crates/layerfs-telemetry" } napi = "=2.16.17" napi-derive = "=2.16.13" diff --git a/api/layerfs-api/Cargo.toml b/api/layerfs-api/Cargo.toml new file mode 100644 index 000000000..2fecc1ff5 --- /dev/null +++ b/api/layerfs-api/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "layerfs-api" +description = "The SDK's public surface behind the JavaScript SDK, one function per method: project Init and Branches, fs and branch Store methods over layerfs-store-service, and Sandbox control" +version.workspace = true +edition.workspace = true +rust-version.workspace = true +license.workspace = true + +[dependencies] +layerfs-bridge = { path = "../../engine/crates/layerfs-bridge" } +layerfs-content = { path = "../../core/crates/layerfs-content" } +layerfs-history = { path = "../../core/crates/layerfs-history" } +layerfs-persistence = { path = "../../engine/crates/layerfs-persistence" } +layerfs-storage = { path = "../../core/crates/layerfs-storage" } +layerfs-telemetry = { path = "../../core/crates/layerfs-telemetry" } +layerfs-project = { path = "../../engine/crates/layerfs-project" } +layerfs-sandbox = { path = "../../engine/crates/layerfs-sandbox" } +layerfs-store-service = { path = "../../engine/crates/layerfs-store-service" } + +[dev-dependencies] +nix = { version = "=0.31.3", features = ["fs", "user", "process"] } +layerfs-daemon = { path = "../../engine/crates/layerfs-daemon" } +layerfs-fuse = { path = "../../engine/crates/layerfs-fuse" } +# #364: the write-cost harness times BLAKE3 over the bytes it writes. +blake3 = { version = "=1.8.5", default-features = false } +# The Store method tests bind private Workspaces and count the Store's rows. +layerfs-overlay = { path = "../../engine/crates/layerfs-overlay" } +layerfs-workspace = { path = "../../engine/crates/layerfs-workspace" } +rusqlite = { version = "=0.40.2", features = ["cache", "limits", "blob"] } diff --git a/core/crates/layerfs-api/examples/issue367_rm_probe.rs b/api/layerfs-api/examples/issue367_rm_probe.rs similarity index 100% rename from core/crates/layerfs-api/examples/issue367_rm_probe.rs rename to api/layerfs-api/examples/issue367_rm_probe.rs diff --git a/core/crates/layerfs-api/examples/sandbox_kernel_mount.rs b/api/layerfs-api/examples/sandbox_kernel_mount.rs similarity index 100% rename from core/crates/layerfs-api/examples/sandbox_kernel_mount.rs rename to api/layerfs-api/examples/sandbox_kernel_mount.rs diff --git a/core/crates/layerfs-api/examples/sandbox_lifecycle.rs b/api/layerfs-api/examples/sandbox_lifecycle.rs similarity index 100% rename from core/crates/layerfs-api/examples/sandbox_lifecycle.rs rename to api/layerfs-api/examples/sandbox_lifecycle.rs diff --git a/core/crates/layerfs-api/src/base/args.rs b/api/layerfs-api/src/base/args.rs similarity index 100% rename from core/crates/layerfs-api/src/base/args.rs rename to api/layerfs-api/src/base/args.rs diff --git a/core/crates/layerfs-api/src/base/control.rs b/api/layerfs-api/src/base/control.rs similarity index 100% rename from core/crates/layerfs-api/src/base/control.rs rename to api/layerfs-api/src/base/control.rs diff --git a/core/crates/layerfs-api/src/base/dispatch.rs b/api/layerfs-api/src/base/dispatch.rs similarity index 100% rename from core/crates/layerfs-api/src/base/dispatch.rs rename to api/layerfs-api/src/base/dispatch.rs diff --git a/core/crates/layerfs-api/src/base/failure.rs b/api/layerfs-api/src/base/failure.rs similarity index 100% rename from core/crates/layerfs-api/src/base/failure.rs rename to api/layerfs-api/src/base/failure.rs diff --git a/core/crates/layerfs-api/src/base/internal.rs b/api/layerfs-api/src/base/internal.rs similarity index 100% rename from core/crates/layerfs-api/src/base/internal.rs rename to api/layerfs-api/src/base/internal.rs diff --git a/core/crates/layerfs-api/src/base/mod.rs b/api/layerfs-api/src/base/mod.rs similarity index 100% rename from core/crates/layerfs-api/src/base/mod.rs rename to api/layerfs-api/src/base/mod.rs diff --git a/core/crates/layerfs-api/src/base/recovery.rs b/api/layerfs-api/src/base/recovery.rs similarity index 100% rename from core/crates/layerfs-api/src/base/recovery.rs rename to api/layerfs-api/src/base/recovery.rs diff --git a/core/crates/layerfs-api/src/base/sdk.rs b/api/layerfs-api/src/base/sdk.rs similarity index 100% rename from core/crates/layerfs-api/src/base/sdk.rs rename to api/layerfs-api/src/base/sdk.rs diff --git a/core/crates/layerfs-api/src/branch/diff_branches.rs b/api/layerfs-api/src/branch/diff_branches.rs similarity index 100% rename from core/crates/layerfs-api/src/branch/diff_branches.rs rename to api/layerfs-api/src/branch/diff_branches.rs diff --git a/core/crates/layerfs-api/src/branch/diff_commits.rs b/api/layerfs-api/src/branch/diff_commits.rs similarity index 100% rename from core/crates/layerfs-api/src/branch/diff_commits.rs rename to api/layerfs-api/src/branch/diff_commits.rs diff --git a/core/crates/layerfs-api/src/branch/fork.rs b/api/layerfs-api/src/branch/fork.rs similarity index 100% rename from core/crates/layerfs-api/src/branch/fork.rs rename to api/layerfs-api/src/branch/fork.rs diff --git a/core/crates/layerfs-api/src/branch/list_commits.rs b/api/layerfs-api/src/branch/list_commits.rs similarity index 100% rename from core/crates/layerfs-api/src/branch/list_commits.rs rename to api/layerfs-api/src/branch/list_commits.rs diff --git a/core/crates/layerfs-api/src/branch/merge.rs b/api/layerfs-api/src/branch/merge.rs similarity index 100% rename from core/crates/layerfs-api/src/branch/merge.rs rename to api/layerfs-api/src/branch/merge.rs diff --git a/core/crates/layerfs-api/src/branch/mod.rs b/api/layerfs-api/src/branch/mod.rs similarity index 100% rename from core/crates/layerfs-api/src/branch/mod.rs rename to api/layerfs-api/src/branch/mod.rs diff --git a/core/crates/layerfs-api/src/branch/publish.rs b/api/layerfs-api/src/branch/publish.rs similarity index 100% rename from core/crates/layerfs-api/src/branch/publish.rs rename to api/layerfs-api/src/branch/publish.rs diff --git a/core/crates/layerfs-api/src/fs/apply.rs b/api/layerfs-api/src/fs/apply.rs similarity index 100% rename from core/crates/layerfs-api/src/fs/apply.rs rename to api/layerfs-api/src/fs/apply.rs diff --git a/core/crates/layerfs-api/src/fs/blame.rs b/api/layerfs-api/src/fs/blame.rs similarity index 100% rename from core/crates/layerfs-api/src/fs/blame.rs rename to api/layerfs-api/src/fs/blame.rs diff --git a/core/crates/layerfs-api/src/fs/cp.rs b/api/layerfs-api/src/fs/cp.rs similarity index 100% rename from core/crates/layerfs-api/src/fs/cp.rs rename to api/layerfs-api/src/fs/cp.rs diff --git a/core/crates/layerfs-api/src/fs/diff_files.rs b/api/layerfs-api/src/fs/diff_files.rs similarity index 100% rename from core/crates/layerfs-api/src/fs/diff_files.rs rename to api/layerfs-api/src/fs/diff_files.rs diff --git a/core/crates/layerfs-api/src/fs/edit.rs b/api/layerfs-api/src/fs/edit.rs similarity index 100% rename from core/crates/layerfs-api/src/fs/edit.rs rename to api/layerfs-api/src/fs/edit.rs diff --git a/core/crates/layerfs-api/src/fs/glob.rs b/api/layerfs-api/src/fs/glob.rs similarity index 100% rename from core/crates/layerfs-api/src/fs/glob.rs rename to api/layerfs-api/src/fs/glob.rs diff --git a/core/crates/layerfs-api/src/fs/grep.rs b/api/layerfs-api/src/fs/grep.rs similarity index 100% rename from core/crates/layerfs-api/src/fs/grep.rs rename to api/layerfs-api/src/fs/grep.rs diff --git a/core/crates/layerfs-api/src/fs/list.rs b/api/layerfs-api/src/fs/list.rs similarity index 100% rename from core/crates/layerfs-api/src/fs/list.rs rename to api/layerfs-api/src/fs/list.rs diff --git a/core/crates/layerfs-api/src/fs/mkdir.rs b/api/layerfs-api/src/fs/mkdir.rs similarity index 100% rename from core/crates/layerfs-api/src/fs/mkdir.rs rename to api/layerfs-api/src/fs/mkdir.rs diff --git a/core/crates/layerfs-api/src/fs/mod.rs b/api/layerfs-api/src/fs/mod.rs similarity index 100% rename from core/crates/layerfs-api/src/fs/mod.rs rename to api/layerfs-api/src/fs/mod.rs diff --git a/core/crates/layerfs-api/src/fs/mv.rs b/api/layerfs-api/src/fs/mv.rs similarity index 100% rename from core/crates/layerfs-api/src/fs/mv.rs rename to api/layerfs-api/src/fs/mv.rs diff --git a/core/crates/layerfs-api/src/fs/read.rs b/api/layerfs-api/src/fs/read.rs similarity index 100% rename from core/crates/layerfs-api/src/fs/read.rs rename to api/layerfs-api/src/fs/read.rs diff --git a/core/crates/layerfs-api/src/fs/rm.rs b/api/layerfs-api/src/fs/rm.rs similarity index 100% rename from core/crates/layerfs-api/src/fs/rm.rs rename to api/layerfs-api/src/fs/rm.rs diff --git a/core/crates/layerfs-api/src/fs/stat.rs b/api/layerfs-api/src/fs/stat.rs similarity index 100% rename from core/crates/layerfs-api/src/fs/stat.rs rename to api/layerfs-api/src/fs/stat.rs diff --git a/core/crates/layerfs-api/src/fs/write.rs b/api/layerfs-api/src/fs/write.rs similarity index 100% rename from core/crates/layerfs-api/src/fs/write.rs rename to api/layerfs-api/src/fs/write.rs diff --git a/core/crates/layerfs-api/src/lib.rs b/api/layerfs-api/src/lib.rs similarity index 100% rename from core/crates/layerfs-api/src/lib.rs rename to api/layerfs-api/src/lib.rs diff --git a/core/crates/layerfs-api/src/operator/call.rs b/api/layerfs-api/src/operator/call.rs similarity index 100% rename from core/crates/layerfs-api/src/operator/call.rs rename to api/layerfs-api/src/operator/call.rs diff --git a/core/crates/layerfs-api/src/operator/inspect/mod.rs b/api/layerfs-api/src/operator/inspect/mod.rs similarity index 100% rename from core/crates/layerfs-api/src/operator/inspect/mod.rs rename to api/layerfs-api/src/operator/inspect/mod.rs diff --git a/core/crates/layerfs-api/src/operator/inspect/snapshot.rs b/api/layerfs-api/src/operator/inspect/snapshot.rs similarity index 100% rename from core/crates/layerfs-api/src/operator/inspect/snapshot.rs rename to api/layerfs-api/src/operator/inspect/snapshot.rs diff --git a/core/crates/layerfs-api/src/operator/mod.rs b/api/layerfs-api/src/operator/mod.rs similarity index 100% rename from core/crates/layerfs-api/src/operator/mod.rs rename to api/layerfs-api/src/operator/mod.rs diff --git a/core/crates/layerfs-api/src/project/list_branches.rs b/api/layerfs-api/src/project/list_branches.rs similarity index 100% rename from core/crates/layerfs-api/src/project/list_branches.rs rename to api/layerfs-api/src/project/list_branches.rs diff --git a/core/crates/layerfs-api/src/project/mod.rs b/api/layerfs-api/src/project/mod.rs similarity index 100% rename from core/crates/layerfs-api/src/project/mod.rs rename to api/layerfs-api/src/project/mod.rs diff --git a/core/crates/layerfs-api/src/sandbox/close.rs b/api/layerfs-api/src/sandbox/close.rs similarity index 100% rename from core/crates/layerfs-api/src/sandbox/close.rs rename to api/layerfs-api/src/sandbox/close.rs diff --git a/core/crates/layerfs-api/src/sandbox/commit.rs b/api/layerfs-api/src/sandbox/commit.rs similarity index 100% rename from core/crates/layerfs-api/src/sandbox/commit.rs rename to api/layerfs-api/src/sandbox/commit.rs diff --git a/core/crates/layerfs-api/src/sandbox/create.rs b/api/layerfs-api/src/sandbox/create.rs similarity index 100% rename from core/crates/layerfs-api/src/sandbox/create.rs rename to api/layerfs-api/src/sandbox/create.rs diff --git a/core/crates/layerfs-api/src/sandbox/exec.rs b/api/layerfs-api/src/sandbox/exec.rs similarity index 100% rename from core/crates/layerfs-api/src/sandbox/exec.rs rename to api/layerfs-api/src/sandbox/exec.rs diff --git a/core/crates/layerfs-api/src/sandbox/mod.rs b/api/layerfs-api/src/sandbox/mod.rs similarity index 100% rename from core/crates/layerfs-api/src/sandbox/mod.rs rename to api/layerfs-api/src/sandbox/mod.rs diff --git a/core/crates/layerfs-api/src/sandbox/mount.rs b/api/layerfs-api/src/sandbox/mount.rs similarity index 100% rename from core/crates/layerfs-api/src/sandbox/mount.rs rename to api/layerfs-api/src/sandbox/mount.rs diff --git a/core/crates/layerfs-api/src/sandbox/status.rs b/api/layerfs-api/src/sandbox/status.rs similarity index 100% rename from core/crates/layerfs-api/src/sandbox/status.rs rename to api/layerfs-api/src/sandbox/status.rs diff --git a/core/crates/layerfs-api/src/sandbox/unmount.rs b/api/layerfs-api/src/sandbox/unmount.rs similarity index 100% rename from core/crates/layerfs-api/src/sandbox/unmount.rs rename to api/layerfs-api/src/sandbox/unmount.rs diff --git a/core/crates/layerfs-api/src/sandbox/values.rs b/api/layerfs-api/src/sandbox/values.rs similarity index 100% rename from core/crates/layerfs-api/src/sandbox/values.rs rename to api/layerfs-api/src/sandbox/values.rs diff --git a/core/crates/layerfs-api/tests/concurrent_commits.rs b/api/layerfs-api/tests/concurrent_commits.rs similarity index 100% rename from core/crates/layerfs-api/tests/concurrent_commits.rs rename to api/layerfs-api/tests/concurrent_commits.rs diff --git a/core/crates/layerfs-api/tests/diff_replay.rs b/api/layerfs-api/tests/diff_replay.rs similarity index 100% rename from core/crates/layerfs-api/tests/diff_replay.rs rename to api/layerfs-api/tests/diff_replay.rs diff --git a/core/crates/layerfs-api/tests/diff_resume.rs b/api/layerfs-api/tests/diff_resume.rs similarity index 100% rename from core/crates/layerfs-api/tests/diff_resume.rs rename to api/layerfs-api/tests/diff_resume.rs diff --git a/core/crates/layerfs-api/tests/fixtures/merge-forms-root.sqlite b/api/layerfs-api/tests/fixtures/merge-forms-root.sqlite similarity index 100% rename from core/crates/layerfs-api/tests/fixtures/merge-forms-root.sqlite rename to api/layerfs-api/tests/fixtures/merge-forms-root.sqlite diff --git a/core/crates/layerfs-api/tests/golden/sdk_methods.txt b/api/layerfs-api/tests/golden/sdk_methods.txt similarity index 100% rename from core/crates/layerfs-api/tests/golden/sdk_methods.txt rename to api/layerfs-api/tests/golden/sdk_methods.txt diff --git a/core/crates/layerfs-api/tests/history_ancestry_oracle.rs b/api/layerfs-api/tests/history_ancestry_oracle.rs similarity index 100% rename from core/crates/layerfs-api/tests/history_ancestry_oracle.rs rename to api/layerfs-api/tests/history_ancestry_oracle.rs diff --git a/core/crates/layerfs-api/tests/history_diff_oracle.rs b/api/layerfs-api/tests/history_diff_oracle.rs similarity index 100% rename from core/crates/layerfs-api/tests/history_diff_oracle.rs rename to api/layerfs-api/tests/history_diff_oracle.rs diff --git a/core/crates/layerfs-api/tests/init.rs b/api/layerfs-api/tests/init.rs similarity index 100% rename from core/crates/layerfs-api/tests/init.rs rename to api/layerfs-api/tests/init.rs diff --git a/core/crates/layerfs-api/tests/kernel_application.rs b/api/layerfs-api/tests/kernel_application.rs similarity index 98% rename from core/crates/layerfs-api/tests/kernel_application.rs rename to api/layerfs-api/tests/kernel_application.rs index 0d9b1c595..948f0efb4 100644 --- a/core/crates/layerfs-api/tests/kernel_application.rs +++ b/api/layerfs-api/tests/kernel_application.rs @@ -3,7 +3,7 @@ #[path = "support/daemon_binary.rs"] mod daemon_binary; #[allow(dead_code)] -#[path = "../../layerfs-daemon/tests/support/host_install.rs"] +#[path = "../../../engine/crates/layerfs-daemon/tests/support/host_install.rs"] mod support; use layerfs_api::internal::Control; use layerfs_bridge::{ diff --git a/core/crates/layerfs-api/tests/kernel_mount_routes.rs b/api/layerfs-api/tests/kernel_mount_routes.rs similarity index 98% rename from core/crates/layerfs-api/tests/kernel_mount_routes.rs rename to api/layerfs-api/tests/kernel_mount_routes.rs index cca769069..3734fab28 100644 --- a/core/crates/layerfs-api/tests/kernel_mount_routes.rs +++ b/api/layerfs-api/tests/kernel_mount_routes.rs @@ -3,10 +3,10 @@ //! frequent fresh mounts and sustained work on one mount. #![cfg(target_os = "linux")] #[allow(dead_code)] -#[path = "../../layerfs-daemon/tests/support/mounted.rs"] +#[path = "../../../engine/crates/layerfs-daemon/tests/support/mounted.rs"] mod mounted; #[allow(dead_code)] -#[path = "../../layerfs-daemon/tests/support/host_install.rs"] +#[path = "../../../engine/crates/layerfs-daemon/tests/support/host_install.rs"] mod support; use layerfs_api::{internal::Control, OperationCause}; use layerfs_bridge::control::{ diff --git a/core/crates/layerfs-api/tests/lane_merge.rs b/api/layerfs-api/tests/lane_merge.rs similarity index 100% rename from core/crates/layerfs-api/tests/lane_merge.rs rename to api/layerfs-api/tests/lane_merge.rs diff --git a/core/crates/layerfs-api/tests/local_install.rs b/api/layerfs-api/tests/local_install.rs similarity index 100% rename from core/crates/layerfs-api/tests/local_install.rs rename to api/layerfs-api/tests/local_install.rs diff --git a/core/crates/layerfs-api/tests/merge_by_serial.rs b/api/layerfs-api/tests/merge_by_serial.rs similarity index 100% rename from core/crates/layerfs-api/tests/merge_by_serial.rs rename to api/layerfs-api/tests/merge_by_serial.rs diff --git a/core/crates/layerfs-api/tests/merge_forms_fixture.rs b/api/layerfs-api/tests/merge_forms_fixture.rs similarity index 100% rename from core/crates/layerfs-api/tests/merge_forms_fixture.rs rename to api/layerfs-api/tests/merge_forms_fixture.rs diff --git a/core/crates/layerfs-api/tests/merge_metadata_only.rs b/api/layerfs-api/tests/merge_metadata_only.rs similarity index 100% rename from core/crates/layerfs-api/tests/merge_metadata_only.rs rename to api/layerfs-api/tests/merge_metadata_only.rs diff --git a/core/crates/layerfs-api/tests/merge_mixed_forms.rs b/api/layerfs-api/tests/merge_mixed_forms.rs similarity index 100% rename from core/crates/layerfs-api/tests/merge_mixed_forms.rs rename to api/layerfs-api/tests/merge_mixed_forms.rs diff --git a/core/crates/layerfs-api/tests/merge_report.rs b/api/layerfs-api/tests/merge_report.rs similarity index 100% rename from core/crates/layerfs-api/tests/merge_report.rs rename to api/layerfs-api/tests/merge_report.rs diff --git a/core/crates/layerfs-api/tests/merge_root_oracle.rs b/api/layerfs-api/tests/merge_root_oracle.rs similarity index 100% rename from core/crates/layerfs-api/tests/merge_root_oracle.rs rename to api/layerfs-api/tests/merge_root_oracle.rs diff --git a/core/crates/layerfs-api/tests/merge_units.rs b/api/layerfs-api/tests/merge_units.rs similarity index 100% rename from core/crates/layerfs-api/tests/merge_units.rs rename to api/layerfs-api/tests/merge_units.rs diff --git a/core/crates/layerfs-api/tests/method_refusal_order.rs b/api/layerfs-api/tests/method_refusal_order.rs similarity index 100% rename from core/crates/layerfs-api/tests/method_refusal_order.rs rename to api/layerfs-api/tests/method_refusal_order.rs diff --git a/core/crates/layerfs-api/tests/mount_control.rs b/api/layerfs-api/tests/mount_control.rs similarity index 99% rename from core/crates/layerfs-api/tests/mount_control.rs rename to api/layerfs-api/tests/mount_control.rs index fcd075faa..880bddf55 100644 --- a/core/crates/layerfs-api/tests/mount_control.rs +++ b/api/layerfs-api/tests/mount_control.rs @@ -1,10 +1,10 @@ //! Authenticated control over an actually installed Store and one real owner. -#[path = "../../layerfs-daemon/tests/support/control_fixture.rs"] +#[path = "../../../engine/crates/layerfs-daemon/tests/support/control_fixture.rs"] mod fixture; -#[path = "../../layerfs-daemon/tests/support/held_writer.rs"] +#[path = "../../../engine/crates/layerfs-daemon/tests/support/held_writer.rs"] mod held_writer; #[allow(dead_code)] -#[path = "../../layerfs-daemon/tests/support/host_install.rs"] +#[path = "../../../engine/crates/layerfs-daemon/tests/support/host_install.rs"] mod support; use layerfs_api::{internal::Control, OperationCause}; use layerfs_bridge::control::{Activity, ControlCode, Reply, Request, WorkspaceToken}; diff --git a/core/crates/layerfs-api/tests/observed_application.rs b/api/layerfs-api/tests/observed_application.rs similarity index 99% rename from core/crates/layerfs-api/tests/observed_application.rs rename to api/layerfs-api/tests/observed_application.rs index 280904d3e..94b446e35 100644 --- a/core/crates/layerfs-api/tests/observed_application.rs +++ b/api/layerfs-api/tests/observed_application.rs @@ -3,7 +3,7 @@ #[path = "support/daemon_binary.rs"] mod daemon_binary; #[allow(dead_code)] -#[path = "../../layerfs-daemon/tests/support/host_install.rs"] +#[path = "../../../engine/crates/layerfs-daemon/tests/support/host_install.rs"] mod support; use layerfs_api::internal::Control; #[cfg(target_os = "linux")] diff --git a/core/crates/layerfs-api/tests/observed_control.rs b/api/layerfs-api/tests/observed_control.rs similarity index 100% rename from core/crates/layerfs-api/tests/observed_control.rs rename to api/layerfs-api/tests/observed_control.rs diff --git a/core/crates/layerfs-api/tests/operator_history.rs b/api/layerfs-api/tests/operator_history.rs similarity index 100% rename from core/crates/layerfs-api/tests/operator_history.rs rename to api/layerfs-api/tests/operator_history.rs diff --git a/core/crates/layerfs-api/tests/r5_1_actual_daemon_commit.rs b/api/layerfs-api/tests/r5_1_actual_daemon_commit.rs similarity index 97% rename from core/crates/layerfs-api/tests/r5_1_actual_daemon_commit.rs rename to api/layerfs-api/tests/r5_1_actual_daemon_commit.rs index be1a43155..b73ec480a 100644 --- a/core/crates/layerfs-api/tests/r5_1_actual_daemon_commit.rs +++ b/api/layerfs-api/tests/r5_1_actual_daemon_commit.rs @@ -21,19 +21,19 @@ #[path = "support/daemon_binary.rs"] mod daemon_binary; #[allow(dead_code)] -#[path = "../../layerfs-daemon/tests/support/installed_store.rs"] +#[path = "../../../engine/crates/layerfs-daemon/tests/support/installed_store.rs"] mod installed; #[allow(dead_code)] -#[path = "../../layerfs-daemon/tests/support/namespace_model.rs"] +#[path = "../../../engine/crates/layerfs-daemon/tests/support/namespace_model.rs"] mod model; #[allow(dead_code)] -#[path = "../../layerfs-daemon/tests/support/mounted.rs"] +#[path = "../../../engine/crates/layerfs-daemon/tests/support/mounted.rs"] mod mounted; #[allow(dead_code)] -#[path = "../../layerfs-daemon/tests/support/mounted_commit.rs"] +#[path = "../../../engine/crates/layerfs-daemon/tests/support/mounted_commit.rs"] mod rig; #[allow(dead_code)] -#[path = "../../layerfs-daemon/tests/support/host_install.rs"] +#[path = "../../../engine/crates/layerfs-daemon/tests/support/host_install.rs"] mod support; use layerfs_api::internal::Control; use layerfs_bridge::{ diff --git a/core/crates/layerfs-api/tests/refresh_lookups.rs b/api/layerfs-api/tests/refresh_lookups.rs similarity index 100% rename from core/crates/layerfs-api/tests/refresh_lookups.rs rename to api/layerfs-api/tests/refresh_lookups.rs diff --git a/core/crates/layerfs-api/tests/relink_commit.rs b/api/layerfs-api/tests/relink_commit.rs similarity index 100% rename from core/crates/layerfs-api/tests/relink_commit.rs rename to api/layerfs-api/tests/relink_commit.rs diff --git a/core/crates/layerfs-api/tests/replay_merges.rs b/api/layerfs-api/tests/replay_merges.rs similarity index 100% rename from core/crates/layerfs-api/tests/replay_merges.rs rename to api/layerfs-api/tests/replay_merges.rs diff --git a/core/crates/layerfs-api/tests/sandbox_operations.rs b/api/layerfs-api/tests/sandbox_operations.rs similarity index 99% rename from core/crates/layerfs-api/tests/sandbox_operations.rs rename to api/layerfs-api/tests/sandbox_operations.rs index 64859816e..1b0828e69 100644 --- a/core/crates/layerfs-api/tests/sandbox_operations.rs +++ b/api/layerfs-api/tests/sandbox_operations.rs @@ -1,7 +1,7 @@ //! Bounded original Engine/control peers qualify SDK close custody and ordinary exec routing. #![cfg(unix)] #[allow(dead_code)] -#[path = "../../layerfs-sandbox/tests/support/engine.rs"] +#[path = "../../../engine/crates/layerfs-sandbox/tests/support/engine.rs"] mod engine; use engine::{fixed, frame, Peer}; use layerfs_api::{ diff --git a/core/crates/layerfs-api/tests/scale_lineage_cap.rs b/api/layerfs-api/tests/scale_lineage_cap.rs similarity index 100% rename from core/crates/layerfs-api/tests/scale_lineage_cap.rs rename to api/layerfs-api/tests/scale_lineage_cap.rs diff --git a/core/crates/layerfs-api/tests/sdk_branch_count.rs b/api/layerfs-api/tests/sdk_branch_count.rs similarity index 100% rename from core/crates/layerfs-api/tests/sdk_branch_count.rs rename to api/layerfs-api/tests/sdk_branch_count.rs diff --git a/core/crates/layerfs-api/tests/sdk_chunk_deltas.rs b/api/layerfs-api/tests/sdk_chunk_deltas.rs similarity index 100% rename from core/crates/layerfs-api/tests/sdk_chunk_deltas.rs rename to api/layerfs-api/tests/sdk_chunk_deltas.rs diff --git a/core/crates/layerfs-api/tests/sdk_compare.rs b/api/layerfs-api/tests/sdk_compare.rs similarity index 100% rename from core/crates/layerfs-api/tests/sdk_compare.rs rename to api/layerfs-api/tests/sdk_compare.rs diff --git a/core/crates/layerfs-api/tests/sdk_diff_entries.rs b/api/layerfs-api/tests/sdk_diff_entries.rs similarity index 100% rename from core/crates/layerfs-api/tests/sdk_diff_entries.rs rename to api/layerfs-api/tests/sdk_diff_entries.rs diff --git a/core/crates/layerfs-api/tests/sdk_diff_pages.rs b/api/layerfs-api/tests/sdk_diff_pages.rs similarity index 100% rename from core/crates/layerfs-api/tests/sdk_diff_pages.rs rename to api/layerfs-api/tests/sdk_diff_pages.rs diff --git a/core/crates/layerfs-api/tests/sdk_diff_size.rs b/api/layerfs-api/tests/sdk_diff_size.rs similarity index 100% rename from core/crates/layerfs-api/tests/sdk_diff_size.rs rename to api/layerfs-api/tests/sdk_diff_size.rs diff --git a/core/crates/layerfs-api/tests/sdk_fixed_costs.rs b/api/layerfs-api/tests/sdk_fixed_costs.rs similarity index 100% rename from core/crates/layerfs-api/tests/sdk_fixed_costs.rs rename to api/layerfs-api/tests/sdk_fixed_costs.rs diff --git a/core/crates/layerfs-api/tests/sdk_fs_reads_replay.rs b/api/layerfs-api/tests/sdk_fs_reads_replay.rs similarity index 100% rename from core/crates/layerfs-api/tests/sdk_fs_reads_replay.rs rename to api/layerfs-api/tests/sdk_fs_reads_replay.rs diff --git a/core/crates/layerfs-api/tests/sdk_grep_reads.rs b/api/layerfs-api/tests/sdk_grep_reads.rs similarity index 100% rename from core/crates/layerfs-api/tests/sdk_grep_reads.rs rename to api/layerfs-api/tests/sdk_grep_reads.rs diff --git a/core/crates/layerfs-api/tests/sdk_history_depth.rs b/api/layerfs-api/tests/sdk_history_depth.rs similarity index 100% rename from core/crates/layerfs-api/tests/sdk_history_depth.rs rename to api/layerfs-api/tests/sdk_history_depth.rs diff --git a/core/crates/layerfs-api/tests/sdk_list_entries.rs b/api/layerfs-api/tests/sdk_list_entries.rs similarity index 100% rename from core/crates/layerfs-api/tests/sdk_list_entries.rs rename to api/layerfs-api/tests/sdk_list_entries.rs diff --git a/core/crates/layerfs-api/tests/sdk_merge_diagnostics.rs b/api/layerfs-api/tests/sdk_merge_diagnostics.rs similarity index 100% rename from core/crates/layerfs-api/tests/sdk_merge_diagnostics.rs rename to api/layerfs-api/tests/sdk_merge_diagnostics.rs diff --git a/core/crates/layerfs-api/tests/sdk_merge_paths.rs b/api/layerfs-api/tests/sdk_merge_paths.rs similarity index 100% rename from core/crates/layerfs-api/tests/sdk_merge_paths.rs rename to api/layerfs-api/tests/sdk_merge_paths.rs diff --git a/core/crates/layerfs-api/tests/sdk_merge_scale.rs b/api/layerfs-api/tests/sdk_merge_scale.rs similarity index 100% rename from core/crates/layerfs-api/tests/sdk_merge_scale.rs rename to api/layerfs-api/tests/sdk_merge_scale.rs diff --git a/core/crates/layerfs-api/tests/sdk_method_golden.rs b/api/layerfs-api/tests/sdk_method_golden.rs similarity index 100% rename from core/crates/layerfs-api/tests/sdk_method_golden.rs rename to api/layerfs-api/tests/sdk_method_golden.rs diff --git a/core/crates/layerfs-api/tests/sdk_mount_lookup.rs b/api/layerfs-api/tests/sdk_mount_lookup.rs similarity index 100% rename from core/crates/layerfs-api/tests/sdk_mount_lookup.rs rename to api/layerfs-api/tests/sdk_mount_lookup.rs diff --git a/core/crates/layerfs-api/tests/sdk_project_count.rs b/api/layerfs-api/tests/sdk_project_count.rs similarity index 100% rename from core/crates/layerfs-api/tests/sdk_project_count.rs rename to api/layerfs-api/tests/sdk_project_count.rs diff --git a/core/crates/layerfs-api/tests/sdk_reads_during_publish.rs b/api/layerfs-api/tests/sdk_reads_during_publish.rs similarity index 100% rename from core/crates/layerfs-api/tests/sdk_reads_during_publish.rs rename to api/layerfs-api/tests/sdk_reads_during_publish.rs diff --git a/core/crates/layerfs-api/tests/sdk_reads_under_publish.rs b/api/layerfs-api/tests/sdk_reads_under_publish.rs similarity index 100% rename from core/crates/layerfs-api/tests/sdk_reads_under_publish.rs rename to api/layerfs-api/tests/sdk_reads_under_publish.rs diff --git a/core/crates/layerfs-api/tests/sdk_text_scan.rs b/api/layerfs-api/tests/sdk_text_scan.rs similarity index 100% rename from core/crates/layerfs-api/tests/sdk_text_scan.rs rename to api/layerfs-api/tests/sdk_text_scan.rs diff --git a/core/crates/layerfs-api/tests/sdk_timing_coverage.rs b/api/layerfs-api/tests/sdk_timing_coverage.rs similarity index 100% rename from core/crates/layerfs-api/tests/sdk_timing_coverage.rs rename to api/layerfs-api/tests/sdk_timing_coverage.rs diff --git a/core/crates/layerfs-api/tests/sdk_written_back.rs b/api/layerfs-api/tests/sdk_written_back.rs similarity index 100% rename from core/crates/layerfs-api/tests/sdk_written_back.rs rename to api/layerfs-api/tests/sdk_written_back.rs diff --git a/core/crates/layerfs-api/tests/support/daemon_binary.rs b/api/layerfs-api/tests/support/daemon_binary.rs similarity index 100% rename from core/crates/layerfs-api/tests/support/daemon_binary.rs rename to api/layerfs-api/tests/support/daemon_binary.rs diff --git a/core/crates/layerfs-api/tests/support/installed_store.rs b/api/layerfs-api/tests/support/installed_store.rs similarity index 100% rename from core/crates/layerfs-api/tests/support/installed_store.rs rename to api/layerfs-api/tests/support/installed_store.rs diff --git a/core/crates/layerfs-api/tests/support/sdk.rs b/api/layerfs-api/tests/support/sdk.rs similarity index 100% rename from core/crates/layerfs-api/tests/support/sdk.rs rename to api/layerfs-api/tests/support/sdk.rs diff --git a/core/crates/layerfs-api/tests/support/view.rs b/api/layerfs-api/tests/support/view.rs similarity index 100% rename from core/crates/layerfs-api/tests/support/view.rs rename to api/layerfs-api/tests/support/view.rs diff --git a/core/crates/layerfs-api/tests/workspace_reader_cache.rs b/api/layerfs-api/tests/workspace_reader_cache.rs similarity index 100% rename from core/crates/layerfs-api/tests/workspace_reader_cache.rs rename to api/layerfs-api/tests/workspace_reader_cache.rs diff --git a/core/crates/layerfs-api/tests/write_cost.rs b/api/layerfs-api/tests/write_cost.rs similarity index 100% rename from core/crates/layerfs-api/tests/write_cost.rs rename to api/layerfs-api/tests/write_cost.rs diff --git a/core/crates/layerfs-api/tests/write_refusals.rs b/api/layerfs-api/tests/write_refusals.rs similarity index 100% rename from core/crates/layerfs-api/tests/write_refusals.rs rename to api/layerfs-api/tests/write_refusals.rs diff --git a/api/scripts/build-native.mjs b/api/scripts/build-native.mjs index ffe3eee82..c69334bb4 100644 --- a/api/scripts/build-native.mjs +++ b/api/scripts/build-native.mjs @@ -12,12 +12,12 @@ const flags = process.argv.slice(2); if (flags.some((flag) => flag !== "--debug")) throw new Error("usage: build-native.mjs [--debug]"); const profile = flags.includes("--debug") ? "debug" : "release"; const configured = process.env.CARGO_TARGET_DIR; -const target = configured ? resolve(root, configured) : join(root, "core/target"); +const target = configured ? resolve(root, configured) : join(root, "target"); const outside = relative(root, target); if (outside.startsWith("..") || isAbsolute(outside)) throw new Error("Cargo target must stay in this worktree"); if (process.env.CARGO_BUILD_TARGET) throw new Error("build on the actual macOS/Linux host without CARGO_BUILD_TARGET"); const result = spawnSync("cargo", [ - "+1.85.1", "build", "--manifest-path", "core/Cargo.toml", "--offline", "--locked", + "+1.85.1", "build", "--manifest-path", "Cargo.toml", "--offline", "--locked", ...(profile === "release" ? ["--release"] : []), "-p", "layerfs-node", ], { cwd: root, stdio: "inherit", env: { ...process.env, CARGO_TARGET_DIR: target } }); if (result.error) throw result.error; diff --git a/core/Cargo.toml b/core/Cargo.toml deleted file mode 100644 index 7dad72994..000000000 --- a/core/Cargo.toml +++ /dev/null @@ -1,49 +0,0 @@ -# Independent replacement-product workspace (LayerFS v1.1.0). -# -# The reference workspace at the repository root keeps its own members, lockfile -# and target directory; `core/` is excluded there. The candidate components under -# implementation are layerfs-telemetry (timer), layerfs-content (C1) and -# layerfs-storage (C2). Further packages are added with their real boundaries. -# Third-party pins are added with the component that needs them. - -[workspace] -resolver = "2" -members = [ - "crates/layerfs-content", - "crates/layerfs-storage", - "crates/layerfs-persistence", - "crates/layerfs-project", - "crates/layerfs-history", - "crates/layerfs-telemetry", - "crates/layerfs-overlay", - "crates/layerfs-workspace", - "crates/layerfs-store-service", - "crates/layerfs-daemon", - "crates/layerfs-api", - "crates/layerfs-bridge", - "crates/layerfs-sandbox", - "crates/layerfs-fuse", - # Node binding of the JavaScript SDK (owner-approved napi-rs, 2026-10-15). - "../api/binding", -] -exclude = [ - "vendor/fuser-0.18.0", -] - -[workspace.package] -edition = "2021" -version = "1.1.0" -rust-version = "1.85" -license = "MIT" - -# Keep the large boundary fixtures cheap without removing cases or assertions. -# Product dev/release profiles and test debug assertions stay unchanged. -[profile.test] -opt-level = 1 - -[profile.test.package.zstd-sys] -opt-level = 3 - -# Owner-authorized signed-timestamp correction to the crates.io 0.18.0 archive. -[patch.crates-io] -fuser = { version = "=0.18.0", path = "vendor/fuser-0.18.0" } diff --git a/core/crates/layerfs-api/Cargo.toml b/core/crates/layerfs-api/Cargo.toml deleted file mode 100644 index 335755733..000000000 --- a/core/crates/layerfs-api/Cargo.toml +++ /dev/null @@ -1,29 +0,0 @@ -[package] -name = "layerfs-api" -description = "The SDK's public surface behind the JavaScript SDK, one function per method: project Init and Branches, fs and branch Store methods over layerfs-store-service, and Sandbox control" -version.workspace = true -edition.workspace = true -rust-version.workspace = true -license.workspace = true - -[dependencies] -layerfs-bridge = { path = "../layerfs-bridge" } -layerfs-content = { path = "../layerfs-content" } -layerfs-history = { path = "../layerfs-history" } -layerfs-persistence = { path = "../layerfs-persistence" } -layerfs-storage = { path = "../layerfs-storage" } -layerfs-telemetry = { path = "../layerfs-telemetry" } -layerfs-project = { path = "../layerfs-project" } -layerfs-sandbox = { path = "../layerfs-sandbox" } -layerfs-store-service = { path = "../layerfs-store-service" } - -[dev-dependencies] -nix = { version = "=0.31.3", features = ["fs", "user", "process"] } -layerfs-daemon = { path = "../layerfs-daemon" } -layerfs-fuse = { path = "../layerfs-fuse" } -# #364: the write-cost harness times BLAKE3 over the bytes it writes. -blake3 = { version = "=1.8.5", default-features = false } -# The Store method tests bind private Workspaces and count the Store's rows. -layerfs-overlay = { path = "../layerfs-overlay" } -layerfs-workspace = { path = "../layerfs-workspace" } -rusqlite = { version = "=0.40.2", features = ["cache", "limits", "blob"] } diff --git a/core/crates/layerfs-content/tests/fixture_seal.rs b/core/crates/layerfs-content/tests/fixture_seal.rs index 67d620119..bdabcca51 100644 --- a/core/crates/layerfs-content/tests/fixture_seal.rs +++ b/core/crates/layerfs-content/tests/fixture_seal.rs @@ -4,7 +4,7 @@ //! that belongs to the reference implementation and is not part of core. It is //! pinned, by blob and recovery commit, in `tests/fixtures/filesystem.generator`, //! with its two contract properties: it is `#[ignore]`d, and it refuses to run -//! without `LAYERFS_SEAL_FIXTURES=1`. This file reads nothing outside `core/` +//! without `LAYERFS_SEAL_FIXTURES=1`. This file reads first-party product/tooling source //! and never writes into the checkout. On every ordinary `cargo test` it //! //! - hashes the sealed directory and compares it with the frozen list in @@ -12,7 +12,7 @@ //! or changed; //! - compares the generator record with the constants below, so the pin and //! the two contract strings cannot drift silently; -//! - reads every Rust source under `core/` and fails when one that could +//! - reads every Rust source in the product layers and tools and fails when one that could //! reseal (it names the gate, or names the sealed directory and writes //! files) lacks either contract string. No such source exists today. //! @@ -238,24 +238,27 @@ fn the_generator_record_is_the_pinned_one() { } #[test] -fn no_source_in_core_can_reseal_during_an_ordinary_test_run() { +fn no_product_source_can_reseal_during_an_ordinary_test_run() { let manifest = Path::new(env!("CARGO_MANIFEST_DIR")); - let core = manifest - .parent() - .and_then(Path::parent) - .expect("core directory"); + let root = manifest.ancestors().nth(3).expect("repository root"); assert!( - core.join("Cargo.toml").is_file() && core.join("crates").is_dir(), - "the scan root is not the core workspace" + root.join("Cargo.toml").is_file() && root.join("core/crates").is_dir(), + "the scan root is not the workspace" ); - let sources = rust_sources(core); + let roots = ["core", "engine", "api/layerfs-api", "api/binding", "tools"] + .map(|relative| root.join(relative)); + let sources: Vec<_> = roots.iter().flat_map(|path| rust_sources(path)).collect(); let guard = manifest.join("tests/fixture_seal.rs"); assert!( sources.contains(&guard), "the scan did not reach this guard's own source" ); + let writers: Vec<_> = roots + .iter() + .flat_map(|path| ungated_writers(path, &guard)) + .collect(); assert_eq!( - ungated_writers(core, &guard), + writers, Vec::::new(), "a source could rewrite the sealed fixtures without the ignore and the gate" ); diff --git a/core/crates/layerfs-telemetry/examples/timer_composition.rs b/core/crates/layerfs-telemetry/examples/timer_composition.rs index c10f6f81a..37eecfd79 100644 --- a/core/crates/layerfs-telemetry/examples/timer_composition.rs +++ b/core/crates/layerfs-telemetry/examples/timer_composition.rs @@ -9,8 +9,8 @@ //! Run with: //! //! ```text -//! cargo run --manifest-path core/Cargo.toml --example timer_composition -//! cargo run --manifest-path core/Cargo.toml --example timer_composition -- /tmp/run-1/timing.json +//! cargo run --manifest-path Cargo.toml --example timer_composition +//! cargo run --manifest-path Cargo.toml --example timer_composition -- /tmp/run-1/timing.json //! ``` use std::fs::OpenOptions; diff --git a/core/crates/layerfs-telemetry/examples/timer_nested.rs b/core/crates/layerfs-telemetry/examples/timer_nested.rs index 36c365687..f20f2ad5a 100644 --- a/core/crates/layerfs-telemetry/examples/timer_nested.rs +++ b/core/crates/layerfs-telemetry/examples/timer_nested.rs @@ -6,7 +6,7 @@ //! Run with: //! //! ```text -//! cargo run --manifest-path core/Cargo.toml --example timer_nested +//! cargo run --manifest-path Cargo.toml --example timer_nested //! ``` use std::io; diff --git a/core/tools/production_loc.py b/core/tools/production_loc.py deleted file mode 100644 index 431e1c3e6..000000000 --- a/core/tools/production_loc.py +++ /dev/null @@ -1,152 +0,0 @@ -#!/usr/bin/env python3 -"""Reproducible first-party production LOC counter (repository AGENTS.md §4). - -Counts nonblank, non-comment source lines of first-party LayerFS product -implementation. Excluded: tests, fixtures, mocks, examples, benchmarks, -development tooling, docs, manifests and generated artifacts. Legacy inline -test modules and `#[cfg(test)]` items are removed before counting. - -Scope: - core core/crates//src/**/*.rs and *.sql (replacement product) - legacy crates/**/*.rs and *.sql (reference implementation; - retired by R9c on 2026-10-10, so this scope is absent and reads 0 at HEAD) - -Usage: python3 core/tools/production_loc.py [--json] [--root DIR] -""" - -import argparse -import json -from pathlib import Path -import re - -SKIP_DIRS = {"target", "node_modules", ".git", "tests", "benches", "examples", "benchmark"} - - -def strip_rust(text): - """Remove comments and every `#[cfg(test)]`-attributed item from Rust text.""" - output = [] - index = 0 - length = len(text) - pending_test_attribute = False - while index < length: - char = text[index] - if char == "/" and index + 1 < length and text[index + 1] == "/": - end = text.find("\n", index) - index = length if end < 0 else end - continue - if char == "/" and index + 1 < length and text[index + 1] == "*": - depth = 1 - index += 2 - while index < length and depth: - if text.startswith("/*", index): - depth += 1 - index += 2 - elif text.startswith("*/", index): - depth -= 1 - index += 2 - else: - index += 1 - continue - if text.startswith("#[cfg(test)]", index) or text.startswith("#[cfg(any(test", index): - pending_test_attribute = True - index = text.find("\n", index) - index = length if index < 0 else index + 1 - continue - if char == '"': - raw = re.match(r'r(#*)"', text[index:]) - if raw: - terminator = '"' + raw.group(1) - end = text.find(terminator, index + raw.end()) - end = length if end < 0 else end + len(terminator) - output.append(text[index:end]) - index = end - continue - index += 1 - while index < length: - if text[index] == "\\": - index += 2 - continue - if text[index] == '"': - index += 1 - break - index += 1 - output.append('""') - continue - if char == "'": - end = re.match(r"'(?:\\.|[^\\'])'", text[index:]) - if end: - output.append("'x'") - index += end.end() - continue - if pending_test_attribute: - # Skip the attributed item: from its first '{' to the matching '}'. - brace = text.find("{", index) - semicolon = text.find(";", index) - if brace < 0 or (0 <= semicolon < brace): - index = length if semicolon < 0 else semicolon + 1 - pending_test_attribute = False - continue - depth = 0 - cursor = brace - while cursor < length: - if text[cursor] == "{": - depth += 1 - elif text[cursor] == "}": - depth -= 1 - if depth == 0: - cursor += 1 - break - cursor += 1 - index = cursor - pending_test_attribute = False - continue - output.append(char) - index += 1 - return "".join(output) - - -def strip_sql(text): - text = re.sub(r"/\*.*?\*/", "", text, flags=re.S) - return "\n".join(re.sub(r"--.*$", "", line) for line in text.splitlines()) - - -def counted(path): - body = path.read_text(errors="replace") - body = strip_rust(body) if path.suffix == ".rs" else strip_sql(body) - return sum(1 for line in body.splitlines() if line.strip()) - - -def scope_files(root): - groups = {"core": [], "legacy": []} - for path in sorted((root / "core/crates").glob("**/*")): - if path.suffix in (".rs", ".sql") and path.is_file(): - parts = set(path.parts) - if parts & SKIP_DIRS or "src" not in path.parts: - continue - groups["core"].append(path) - for path in sorted((root / "crates").glob("**/*")): - if path.suffix in (".rs", ".sql") and path.is_file(): - if set(path.parts) & SKIP_DIRS: - continue - groups["legacy"].append(path) - return groups - - -def main(): - parser = argparse.ArgumentParser() - parser.add_argument("--json", action="store_true") - parser.add_argument("--root", default=str(Path(__file__).resolve().parents[2])) - arguments = parser.parse_args() - root = Path(arguments.root).resolve() - groups = scope_files(root) - totals = {name: sum(counted(path) for path in paths) for name, paths in groups.items()} - totals["combined"] = totals["core"] + totals["legacy"] - totals["files"] = {name: len(paths) for name, paths in groups.items()} - if arguments.json: - print(json.dumps(totals, sort_keys=True)) - else: - print(f"core {totals['core']} legacy {totals['legacy']} combined {totals['combined']} files {totals['files']}") - - -if __name__ == "__main__": - main() diff --git a/core/crates/layerfs-bridge/Cargo.toml b/engine/crates/layerfs-bridge/Cargo.toml similarity index 78% rename from core/crates/layerfs-bridge/Cargo.toml rename to engine/crates/layerfs-bridge/Cargo.toml index 4c533cc56..4f16e63bd 100644 --- a/core/crates/layerfs-bridge/Cargo.toml +++ b/engine/crates/layerfs-bridge/Cargo.toml @@ -11,8 +11,8 @@ default = ["duplex"] duplex = ["dep:snow"] [dependencies] -layerfs-content = { path = "../layerfs-content" } -layerfs-history = { path = "../layerfs-history" } +layerfs-content = { path = "../../../core/crates/layerfs-content" } +layerfs-history = { path = "../../../core/crates/layerfs-history" } snow = { version = "=0.9.6", optional = true } [lints.rust] diff --git a/core/crates/layerfs-bridge/src/control.rs b/engine/crates/layerfs-bridge/src/control.rs similarity index 100% rename from core/crates/layerfs-bridge/src/control.rs rename to engine/crates/layerfs-bridge/src/control.rs diff --git a/core/crates/layerfs-bridge/src/control_forced.rs b/engine/crates/layerfs-bridge/src/control_forced.rs similarity index 100% rename from core/crates/layerfs-bridge/src/control_forced.rs rename to engine/crates/layerfs-bridge/src/control_forced.rs diff --git a/core/crates/layerfs-bridge/src/control_history.rs b/engine/crates/layerfs-bridge/src/control_history.rs similarity index 100% rename from core/crates/layerfs-bridge/src/control_history.rs rename to engine/crates/layerfs-bridge/src/control_history.rs diff --git a/core/crates/layerfs-bridge/src/control_merge.rs b/engine/crates/layerfs-bridge/src/control_merge.rs similarity index 100% rename from core/crates/layerfs-bridge/src/control_merge.rs rename to engine/crates/layerfs-bridge/src/control_merge.rs diff --git a/core/crates/layerfs-bridge/src/control_mount.rs b/engine/crates/layerfs-bridge/src/control_mount.rs similarity index 100% rename from core/crates/layerfs-bridge/src/control_mount.rs rename to engine/crates/layerfs-bridge/src/control_mount.rs diff --git a/core/crates/layerfs-bridge/src/control_reply.rs b/engine/crates/layerfs-bridge/src/control_reply.rs similarity index 100% rename from core/crates/layerfs-bridge/src/control_reply.rs rename to engine/crates/layerfs-bridge/src/control_reply.rs diff --git a/core/crates/layerfs-bridge/src/control_request.rs b/engine/crates/layerfs-bridge/src/control_request.rs similarity index 100% rename from core/crates/layerfs-bridge/src/control_request.rs rename to engine/crates/layerfs-bridge/src/control_request.rs diff --git a/core/crates/layerfs-bridge/src/control_sdk.rs b/engine/crates/layerfs-bridge/src/control_sdk.rs similarity index 100% rename from core/crates/layerfs-bridge/src/control_sdk.rs rename to engine/crates/layerfs-bridge/src/control_sdk.rs diff --git a/core/crates/layerfs-bridge/src/control_types.rs b/engine/crates/layerfs-bridge/src/control_types.rs similarity index 100% rename from core/crates/layerfs-bridge/src/control_types.rs rename to engine/crates/layerfs-bridge/src/control_types.rs diff --git a/core/crates/layerfs-bridge/src/control_unmount.rs b/engine/crates/layerfs-bridge/src/control_unmount.rs similarity index 100% rename from core/crates/layerfs-bridge/src/control_unmount.rs rename to engine/crates/layerfs-bridge/src/control_unmount.rs diff --git a/core/crates/layerfs-bridge/src/daemon_setup.rs b/engine/crates/layerfs-bridge/src/daemon_setup.rs similarity index 100% rename from core/crates/layerfs-bridge/src/daemon_setup.rs rename to engine/crates/layerfs-bridge/src/daemon_setup.rs diff --git a/core/crates/layerfs-bridge/src/daemon_types.rs b/engine/crates/layerfs-bridge/src/daemon_types.rs similarity index 100% rename from core/crates/layerfs-bridge/src/daemon_types.rs rename to engine/crates/layerfs-bridge/src/daemon_types.rs diff --git a/core/crates/layerfs-bridge/src/daemon_wire.rs b/engine/crates/layerfs-bridge/src/daemon_wire.rs similarity index 100% rename from core/crates/layerfs-bridge/src/daemon_wire.rs rename to engine/crates/layerfs-bridge/src/daemon_wire.rs diff --git a/core/crates/layerfs-bridge/src/duplex/channel.rs b/engine/crates/layerfs-bridge/src/duplex/channel.rs similarity index 100% rename from core/crates/layerfs-bridge/src/duplex/channel.rs rename to engine/crates/layerfs-bridge/src/duplex/channel.rs diff --git a/core/crates/layerfs-bridge/src/duplex/ending.rs b/engine/crates/layerfs-bridge/src/duplex/ending.rs similarity index 100% rename from core/crates/layerfs-bridge/src/duplex/ending.rs rename to engine/crates/layerfs-bridge/src/duplex/ending.rs diff --git a/core/crates/layerfs-bridge/src/duplex/error.rs b/engine/crates/layerfs-bridge/src/duplex/error.rs similarity index 100% rename from core/crates/layerfs-bridge/src/duplex/error.rs rename to engine/crates/layerfs-bridge/src/duplex/error.rs diff --git a/core/crates/layerfs-bridge/src/duplex/handshake.rs b/engine/crates/layerfs-bridge/src/duplex/handshake.rs similarity index 100% rename from core/crates/layerfs-bridge/src/duplex/handshake.rs rename to engine/crates/layerfs-bridge/src/duplex/handshake.rs diff --git a/core/crates/layerfs-bridge/src/duplex/io.rs b/engine/crates/layerfs-bridge/src/duplex/io.rs similarity index 100% rename from core/crates/layerfs-bridge/src/duplex/io.rs rename to engine/crates/layerfs-bridge/src/duplex/io.rs diff --git a/core/crates/layerfs-bridge/src/duplex/mod.rs b/engine/crates/layerfs-bridge/src/duplex/mod.rs similarity index 100% rename from core/crates/layerfs-bridge/src/duplex/mod.rs rename to engine/crates/layerfs-bridge/src/duplex/mod.rs diff --git a/core/crates/layerfs-bridge/src/duplex/profile.rs b/engine/crates/layerfs-bridge/src/duplex/profile.rs similarity index 100% rename from core/crates/layerfs-bridge/src/duplex/profile.rs rename to engine/crates/layerfs-bridge/src/duplex/profile.rs diff --git a/core/crates/layerfs-bridge/src/duplex/types.rs b/engine/crates/layerfs-bridge/src/duplex/types.rs similarity index 100% rename from core/crates/layerfs-bridge/src/duplex/types.rs rename to engine/crates/layerfs-bridge/src/duplex/types.rs diff --git a/core/crates/layerfs-bridge/src/initial_record.rs b/engine/crates/layerfs-bridge/src/initial_record.rs similarity index 100% rename from core/crates/layerfs-bridge/src/initial_record.rs rename to engine/crates/layerfs-bridge/src/initial_record.rs diff --git a/core/crates/layerfs-bridge/src/lib.rs b/engine/crates/layerfs-bridge/src/lib.rs similarity index 100% rename from core/crates/layerfs-bridge/src/lib.rs rename to engine/crates/layerfs-bridge/src/lib.rs diff --git a/core/crates/layerfs-bridge/src/provision.rs b/engine/crates/layerfs-bridge/src/provision.rs similarity index 100% rename from core/crates/layerfs-bridge/src/provision.rs rename to engine/crates/layerfs-bridge/src/provision.rs diff --git a/core/crates/layerfs-bridge/src/provision_wire.rs b/engine/crates/layerfs-bridge/src/provision_wire.rs similarity index 100% rename from core/crates/layerfs-bridge/src/provision_wire.rs rename to engine/crates/layerfs-bridge/src/provision_wire.rs diff --git a/core/crates/layerfs-bridge/src/sdk_merge_values.rs b/engine/crates/layerfs-bridge/src/sdk_merge_values.rs similarity index 100% rename from core/crates/layerfs-bridge/src/sdk_merge_values.rs rename to engine/crates/layerfs-bridge/src/sdk_merge_values.rs diff --git a/core/crates/layerfs-bridge/src/sdk_values.rs b/engine/crates/layerfs-bridge/src/sdk_values.rs similarity index 100% rename from core/crates/layerfs-bridge/src/sdk_values.rs rename to engine/crates/layerfs-bridge/src/sdk_values.rs diff --git a/core/crates/layerfs-bridge/src/wire.rs b/engine/crates/layerfs-bridge/src/wire.rs similarity index 100% rename from core/crates/layerfs-bridge/src/wire.rs rename to engine/crates/layerfs-bridge/src/wire.rs diff --git a/core/crates/layerfs-bridge/tests/control_records.rs b/engine/crates/layerfs-bridge/tests/control_records.rs similarity index 100% rename from core/crates/layerfs-bridge/tests/control_records.rs rename to engine/crates/layerfs-bridge/tests/control_records.rs diff --git a/core/crates/layerfs-bridge/tests/duplex.rs b/engine/crates/layerfs-bridge/tests/duplex.rs similarity index 100% rename from core/crates/layerfs-bridge/tests/duplex.rs rename to engine/crates/layerfs-bridge/tests/duplex.rs diff --git a/core/crates/layerfs-bridge/tests/install_records.rs b/engine/crates/layerfs-bridge/tests/install_records.rs similarity index 100% rename from core/crates/layerfs-bridge/tests/install_records.rs rename to engine/crates/layerfs-bridge/tests/install_records.rs diff --git a/core/crates/layerfs-bridge/tests/observed_records.rs b/engine/crates/layerfs-bridge/tests/observed_records.rs similarity index 100% rename from core/crates/layerfs-bridge/tests/observed_records.rs rename to engine/crates/layerfs-bridge/tests/observed_records.rs diff --git a/core/crates/layerfs-bridge/tests/sdk_merge_values.rs b/engine/crates/layerfs-bridge/tests/sdk_merge_values.rs similarity index 100% rename from core/crates/layerfs-bridge/tests/sdk_merge_values.rs rename to engine/crates/layerfs-bridge/tests/sdk_merge_values.rs diff --git a/core/crates/layerfs-daemon/Cargo.toml b/engine/crates/layerfs-daemon/Cargo.toml similarity index 75% rename from core/crates/layerfs-daemon/Cargo.toml rename to engine/crates/layerfs-daemon/Cargo.toml index bf16e61e7..ea1573865 100644 --- a/core/crates/layerfs-daemon/Cargo.toml +++ b/engine/crates/layerfs-daemon/Cargo.toml @@ -12,10 +12,10 @@ layerfs-store-service = { path = "../layerfs-store-service" } layerfs-workspace = { path = "../layerfs-workspace" } layerfs-fuse = { path = "../layerfs-fuse" } layerfs-bridge = { path = "../layerfs-bridge" } -layerfs-content = { path = "../layerfs-content" } -layerfs-storage = { path = "../layerfs-storage" } -layerfs-history = { path = "../layerfs-history" } -layerfs-telemetry = { path = "../layerfs-telemetry" } +layerfs-content = { path = "../../../core/crates/layerfs-content" } +layerfs-storage = { path = "../../../core/crates/layerfs-storage" } +layerfs-history = { path = "../../../core/crates/layerfs-history" } +layerfs-telemetry = { path = "../../../core/crates/layerfs-telemetry" } # Concrete Store opening stays in application bootstrap, outside store/. layerfs-persistence = { path = "../layerfs-persistence" } diff --git a/core/crates/layerfs-daemon/examples/e2_startup/json.rs b/engine/crates/layerfs-daemon/examples/e2_startup/json.rs similarity index 100% rename from core/crates/layerfs-daemon/examples/e2_startup/json.rs rename to engine/crates/layerfs-daemon/examples/e2_startup/json.rs diff --git a/core/crates/layerfs-daemon/examples/e2_startup/records.rs b/engine/crates/layerfs-daemon/examples/e2_startup/records.rs similarity index 100% rename from core/crates/layerfs-daemon/examples/e2_startup/records.rs rename to engine/crates/layerfs-daemon/examples/e2_startup/records.rs diff --git a/core/crates/layerfs-daemon/examples/resource_growth.rs b/engine/crates/layerfs-daemon/examples/resource_growth.rs similarity index 100% rename from core/crates/layerfs-daemon/examples/resource_growth.rs rename to engine/crates/layerfs-daemon/examples/resource_growth.rs diff --git a/core/crates/layerfs-daemon/examples/resource_growth/allocation.rs b/engine/crates/layerfs-daemon/examples/resource_growth/allocation.rs similarity index 100% rename from core/crates/layerfs-daemon/examples/resource_growth/allocation.rs rename to engine/crates/layerfs-daemon/examples/resource_growth/allocation.rs diff --git a/core/crates/layerfs-daemon/examples/resource_growth/observe.rs b/engine/crates/layerfs-daemon/examples/resource_growth/observe.rs similarity index 100% rename from core/crates/layerfs-daemon/examples/resource_growth/observe.rs rename to engine/crates/layerfs-daemon/examples/resource_growth/observe.rs diff --git a/core/crates/layerfs-daemon/examples/resource_growth/operations.rs b/engine/crates/layerfs-daemon/examples/resource_growth/operations.rs similarity index 100% rename from core/crates/layerfs-daemon/examples/resource_growth/operations.rs rename to engine/crates/layerfs-daemon/examples/resource_growth/operations.rs diff --git a/core/crates/layerfs-daemon/examples/resource_prepare.rs b/engine/crates/layerfs-daemon/examples/resource_prepare.rs similarity index 100% rename from core/crates/layerfs-daemon/examples/resource_prepare.rs rename to engine/crates/layerfs-daemon/examples/resource_prepare.rs diff --git a/core/crates/layerfs-daemon/examples/store_accounting.rs b/engine/crates/layerfs-daemon/examples/store_accounting.rs similarity index 100% rename from core/crates/layerfs-daemon/examples/store_accounting.rs rename to engine/crates/layerfs-daemon/examples/store_accounting.rs diff --git a/core/crates/layerfs-daemon/examples/store_accounting/produce.rs b/engine/crates/layerfs-daemon/examples/store_accounting/produce.rs similarity index 100% rename from core/crates/layerfs-daemon/examples/store_accounting/produce.rs rename to engine/crates/layerfs-daemon/examples/store_accounting/produce.rs diff --git a/core/crates/layerfs-daemon/examples/store_accounting/records.rs b/engine/crates/layerfs-daemon/examples/store_accounting/records.rs similarity index 100% rename from core/crates/layerfs-daemon/examples/store_accounting/records.rs rename to engine/crates/layerfs-daemon/examples/store_accounting/records.rs diff --git a/core/crates/layerfs-daemon/src/application/bodies.rs b/engine/crates/layerfs-daemon/src/application/bodies.rs similarity index 100% rename from core/crates/layerfs-daemon/src/application/bodies.rs rename to engine/crates/layerfs-daemon/src/application/bodies.rs diff --git a/core/crates/layerfs-daemon/src/application/cli.rs b/engine/crates/layerfs-daemon/src/application/cli.rs similarity index 100% rename from core/crates/layerfs-daemon/src/application/cli.rs rename to engine/crates/layerfs-daemon/src/application/cli.rs diff --git a/core/crates/layerfs-daemon/src/application/config.rs b/engine/crates/layerfs-daemon/src/application/config.rs similarity index 100% rename from core/crates/layerfs-daemon/src/application/config.rs rename to engine/crates/layerfs-daemon/src/application/config.rs diff --git a/core/crates/layerfs-daemon/src/application/connection.rs b/engine/crates/layerfs-daemon/src/application/connection.rs similarity index 100% rename from core/crates/layerfs-daemon/src/application/connection.rs rename to engine/crates/layerfs-daemon/src/application/connection.rs diff --git a/core/crates/layerfs-daemon/src/application/diagnostics.rs b/engine/crates/layerfs-daemon/src/application/diagnostics.rs similarity index 100% rename from core/crates/layerfs-daemon/src/application/diagnostics.rs rename to engine/crates/layerfs-daemon/src/application/diagnostics.rs diff --git a/core/crates/layerfs-daemon/src/application/diagnostics/kernel.rs b/engine/crates/layerfs-daemon/src/application/diagnostics/kernel.rs similarity index 100% rename from core/crates/layerfs-daemon/src/application/diagnostics/kernel.rs rename to engine/crates/layerfs-daemon/src/application/diagnostics/kernel.rs diff --git a/core/crates/layerfs-daemon/src/application/diagnostics/resources.rs b/engine/crates/layerfs-daemon/src/application/diagnostics/resources.rs similarity index 100% rename from core/crates/layerfs-daemon/src/application/diagnostics/resources.rs rename to engine/crates/layerfs-daemon/src/application/diagnostics/resources.rs diff --git a/core/crates/layerfs-daemon/src/application/diagnostics/schema.rs b/engine/crates/layerfs-daemon/src/application/diagnostics/schema.rs similarity index 100% rename from core/crates/layerfs-daemon/src/application/diagnostics/schema.rs rename to engine/crates/layerfs-daemon/src/application/diagnostics/schema.rs diff --git a/core/crates/layerfs-daemon/src/application/failure.rs b/engine/crates/layerfs-daemon/src/application/failure.rs similarity index 100% rename from core/crates/layerfs-daemon/src/application/failure.rs rename to engine/crates/layerfs-daemon/src/application/failure.rs diff --git a/core/crates/layerfs-daemon/src/application/filesystem.rs b/engine/crates/layerfs-daemon/src/application/filesystem.rs similarity index 100% rename from core/crates/layerfs-daemon/src/application/filesystem.rs rename to engine/crates/layerfs-daemon/src/application/filesystem.rs diff --git a/core/crates/layerfs-daemon/src/application/idle.rs b/engine/crates/layerfs-daemon/src/application/idle.rs similarity index 100% rename from core/crates/layerfs-daemon/src/application/idle.rs rename to engine/crates/layerfs-daemon/src/application/idle.rs diff --git a/core/crates/layerfs-daemon/src/application/mod.rs b/engine/crates/layerfs-daemon/src/application/mod.rs similarity index 100% rename from core/crates/layerfs-daemon/src/application/mod.rs rename to engine/crates/layerfs-daemon/src/application/mod.rs diff --git a/core/crates/layerfs-daemon/src/application/owner.rs b/engine/crates/layerfs-daemon/src/application/owner.rs similarity index 100% rename from core/crates/layerfs-daemon/src/application/owner.rs rename to engine/crates/layerfs-daemon/src/application/owner.rs diff --git a/core/crates/layerfs-daemon/src/application/serve.rs b/engine/crates/layerfs-daemon/src/application/serve.rs similarity index 100% rename from core/crates/layerfs-daemon/src/application/serve.rs rename to engine/crates/layerfs-daemon/src/application/serve.rs diff --git a/core/crates/layerfs-daemon/src/bin/layerfs-daemon.rs b/engine/crates/layerfs-daemon/src/bin/layerfs-daemon.rs similarity index 100% rename from core/crates/layerfs-daemon/src/bin/layerfs-daemon.rs rename to engine/crates/layerfs-daemon/src/bin/layerfs-daemon.rs diff --git a/core/crates/layerfs-daemon/src/control/attach.rs b/engine/crates/layerfs-daemon/src/control/attach.rs similarity index 100% rename from core/crates/layerfs-daemon/src/control/attach.rs rename to engine/crates/layerfs-daemon/src/control/attach.rs diff --git a/core/crates/layerfs-daemon/src/control/cleanup.rs b/engine/crates/layerfs-daemon/src/control/cleanup.rs similarity index 100% rename from core/crates/layerfs-daemon/src/control/cleanup.rs rename to engine/crates/layerfs-daemon/src/control/cleanup.rs diff --git a/core/crates/layerfs-daemon/src/control/detach.rs b/engine/crates/layerfs-daemon/src/control/detach.rs similarity index 100% rename from core/crates/layerfs-daemon/src/control/detach.rs rename to engine/crates/layerfs-daemon/src/control/detach.rs diff --git a/core/crates/layerfs-daemon/src/control/dirty.rs b/engine/crates/layerfs-daemon/src/control/dirty.rs similarity index 100% rename from core/crates/layerfs-daemon/src/control/dirty.rs rename to engine/crates/layerfs-daemon/src/control/dirty.rs diff --git a/core/crates/layerfs-daemon/src/control/failure.rs b/engine/crates/layerfs-daemon/src/control/failure.rs similarity index 100% rename from core/crates/layerfs-daemon/src/control/failure.rs rename to engine/crates/layerfs-daemon/src/control/failure.rs diff --git a/core/crates/layerfs-daemon/src/control/force.rs b/engine/crates/layerfs-daemon/src/control/force.rs similarity index 100% rename from core/crates/layerfs-daemon/src/control/force.rs rename to engine/crates/layerfs-daemon/src/control/force.rs diff --git a/core/crates/layerfs-daemon/src/control/inspect.rs b/engine/crates/layerfs-daemon/src/control/inspect.rs similarity index 100% rename from core/crates/layerfs-daemon/src/control/inspect.rs rename to engine/crates/layerfs-daemon/src/control/inspect.rs diff --git a/core/crates/layerfs-daemon/src/control/invalidate.rs b/engine/crates/layerfs-daemon/src/control/invalidate.rs similarity index 100% rename from core/crates/layerfs-daemon/src/control/invalidate.rs rename to engine/crates/layerfs-daemon/src/control/invalidate.rs diff --git a/core/crates/layerfs-daemon/src/control/kernel.rs b/engine/crates/layerfs-daemon/src/control/kernel.rs similarity index 100% rename from core/crates/layerfs-daemon/src/control/kernel.rs rename to engine/crates/layerfs-daemon/src/control/kernel.rs diff --git a/core/crates/layerfs-daemon/src/control/mod.rs b/engine/crates/layerfs-daemon/src/control/mod.rs similarity index 100% rename from core/crates/layerfs-daemon/src/control/mod.rs rename to engine/crates/layerfs-daemon/src/control/mod.rs diff --git a/core/crates/layerfs-daemon/src/control/observation.rs b/engine/crates/layerfs-daemon/src/control/observation.rs similarity index 100% rename from core/crates/layerfs-daemon/src/control/observation.rs rename to engine/crates/layerfs-daemon/src/control/observation.rs diff --git a/core/crates/layerfs-daemon/src/control/operations.rs b/engine/crates/layerfs-daemon/src/control/operations.rs similarity index 100% rename from core/crates/layerfs-daemon/src/control/operations.rs rename to engine/crates/layerfs-daemon/src/control/operations.rs diff --git a/core/crates/layerfs-daemon/src/control/registry.rs b/engine/crates/layerfs-daemon/src/control/registry.rs similarity index 100% rename from core/crates/layerfs-daemon/src/control/registry.rs rename to engine/crates/layerfs-daemon/src/control/registry.rs diff --git a/core/crates/layerfs-daemon/src/control/serve.rs b/engine/crates/layerfs-daemon/src/control/serve.rs similarity index 100% rename from core/crates/layerfs-daemon/src/control/serve.rs rename to engine/crates/layerfs-daemon/src/control/serve.rs diff --git a/core/crates/layerfs-daemon/src/control/serving.rs b/engine/crates/layerfs-daemon/src/control/serving.rs similarity index 100% rename from core/crates/layerfs-daemon/src/control/serving.rs rename to engine/crates/layerfs-daemon/src/control/serving.rs diff --git a/core/crates/layerfs-daemon/src/control/status.rs b/engine/crates/layerfs-daemon/src/control/status.rs similarity index 100% rename from core/crates/layerfs-daemon/src/control/status.rs rename to engine/crates/layerfs-daemon/src/control/status.rs diff --git a/core/crates/layerfs-daemon/src/control/types.rs b/engine/crates/layerfs-daemon/src/control/types.rs similarity index 100% rename from core/crates/layerfs-daemon/src/control/types.rs rename to engine/crates/layerfs-daemon/src/control/types.rs diff --git a/core/crates/layerfs-daemon/src/control/unmount.rs b/engine/crates/layerfs-daemon/src/control/unmount.rs similarity index 100% rename from core/crates/layerfs-daemon/src/control/unmount.rs rename to engine/crates/layerfs-daemon/src/control/unmount.rs diff --git a/core/crates/layerfs-daemon/src/install.rs b/engine/crates/layerfs-daemon/src/install.rs similarity index 100% rename from core/crates/layerfs-daemon/src/install.rs rename to engine/crates/layerfs-daemon/src/install.rs diff --git a/core/crates/layerfs-daemon/src/install_file.rs b/engine/crates/layerfs-daemon/src/install_file.rs similarity index 100% rename from core/crates/layerfs-daemon/src/install_file.rs rename to engine/crates/layerfs-daemon/src/install_file.rs diff --git a/core/crates/layerfs-daemon/src/install_types.rs b/engine/crates/layerfs-daemon/src/install_types.rs similarity index 100% rename from core/crates/layerfs-daemon/src/install_types.rs rename to engine/crates/layerfs-daemon/src/install_types.rs diff --git a/core/crates/layerfs-daemon/src/lib.rs b/engine/crates/layerfs-daemon/src/lib.rs similarity index 100% rename from core/crates/layerfs-daemon/src/lib.rs rename to engine/crates/layerfs-daemon/src/lib.rs diff --git a/core/crates/layerfs-daemon/src/operator/dispatch.rs b/engine/crates/layerfs-daemon/src/operator/dispatch.rs similarity index 100% rename from core/crates/layerfs-daemon/src/operator/dispatch.rs rename to engine/crates/layerfs-daemon/src/operator/dispatch.rs diff --git a/core/crates/layerfs-daemon/src/operator/mod.rs b/engine/crates/layerfs-daemon/src/operator/mod.rs similarity index 100% rename from core/crates/layerfs-daemon/src/operator/mod.rs rename to engine/crates/layerfs-daemon/src/operator/mod.rs diff --git a/core/crates/layerfs-daemon/src/operator/workspace.rs b/engine/crates/layerfs-daemon/src/operator/workspace.rs similarity index 100% rename from core/crates/layerfs-daemon/src/operator/workspace.rs rename to engine/crates/layerfs-daemon/src/operator/workspace.rs diff --git a/core/crates/layerfs-daemon/src/service/filesystem_port.rs b/engine/crates/layerfs-daemon/src/service/filesystem_port.rs similarity index 100% rename from core/crates/layerfs-daemon/src/service/filesystem_port.rs rename to engine/crates/layerfs-daemon/src/service/filesystem_port.rs diff --git a/core/crates/layerfs-daemon/src/service/mod.rs b/engine/crates/layerfs-daemon/src/service/mod.rs similarity index 100% rename from core/crates/layerfs-daemon/src/service/mod.rs rename to engine/crates/layerfs-daemon/src/service/mod.rs diff --git a/core/crates/layerfs-daemon/src/telemetry.rs b/engine/crates/layerfs-daemon/src/telemetry.rs similarity index 100% rename from core/crates/layerfs-daemon/src/telemetry.rs rename to engine/crates/layerfs-daemon/src/telemetry.rs diff --git a/core/crates/layerfs-daemon/tests/complete_installed_roots.rs b/engine/crates/layerfs-daemon/tests/complete_installed_roots.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/complete_installed_roots.rs rename to engine/crates/layerfs-daemon/tests/complete_installed_roots.rs diff --git a/core/crates/layerfs-daemon/tests/f046_fork_reference.rs b/engine/crates/layerfs-daemon/tests/f046_fork_reference.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/f046_fork_reference.rs rename to engine/crates/layerfs-daemon/tests/f046_fork_reference.rs diff --git a/core/crates/layerfs-daemon/tests/file_digests.rs b/engine/crates/layerfs-daemon/tests/file_digests.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/file_digests.rs rename to engine/crates/layerfs-daemon/tests/file_digests.rs diff --git a/core/crates/layerfs-daemon/tests/forced_producers.rs b/engine/crates/layerfs-daemon/tests/forced_producers.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/forced_producers.rs rename to engine/crates/layerfs-daemon/tests/forced_producers.rs diff --git a/core/crates/layerfs-daemon/tests/forced_smoke.rs b/engine/crates/layerfs-daemon/tests/forced_smoke.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/forced_smoke.rs rename to engine/crates/layerfs-daemon/tests/forced_smoke.rs diff --git a/core/crates/layerfs-daemon/tests/forced_unavailable.rs b/engine/crates/layerfs-daemon/tests/forced_unavailable.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/forced_unavailable.rs rename to engine/crates/layerfs-daemon/tests/forced_unavailable.rs diff --git a/core/crates/layerfs-daemon/tests/forced_unmount.rs b/engine/crates/layerfs-daemon/tests/forced_unmount.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/forced_unmount.rs rename to engine/crates/layerfs-daemon/tests/forced_unmount.rs diff --git a/core/crates/layerfs-daemon/tests/fp21_detach_stages.rs b/engine/crates/layerfs-daemon/tests/fp21_detach_stages.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/fp21_detach_stages.rs rename to engine/crates/layerfs-daemon/tests/fp21_detach_stages.rs diff --git a/core/crates/layerfs-daemon/tests/fp27_reader_health.rs b/engine/crates/layerfs-daemon/tests/fp27_reader_health.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/fp27_reader_health.rs rename to engine/crates/layerfs-daemon/tests/fp27_reader_health.rs diff --git a/core/crates/layerfs-daemon/tests/fp2_negotiation_flags.rs b/engine/crates/layerfs-daemon/tests/fp2_negotiation_flags.rs similarity index 99% rename from core/crates/layerfs-daemon/tests/fp2_negotiation_flags.rs rename to engine/crates/layerfs-daemon/tests/fp2_negotiation_flags.rs index 21c356dbc..93b56b188 100644 --- a/core/crates/layerfs-daemon/tests/fp2_negotiation_flags.rs +++ b/engine/crates/layerfs-daemon/tests/fp2_negotiation_flags.rs @@ -11,7 +11,7 @@ //! cannot be removed". Every other flag the pinned library knows is asserted //! absent by name, and the twelve flags section 8.1 forbids are asserted //! absent one by one. The names and bit values below are those of -//! `core/vendor/fuser-0.18.0/src/ll/flags/init_flags.rs`; the daemon package +//! `engine/vendor/fuser-0.18.0/src/ll/flags/init_flags.rs`; the daemon package //! has no direct dependency on that library, so they are written here. //! - The receipt's limits are section 8.1's: `max_write` and `max_readahead` //! 131072, `max_background` 1, congestion threshold 1. diff --git a/core/crates/layerfs-daemon/tests/fp31_forget_underflow.rs b/engine/crates/layerfs-daemon/tests/fp31_forget_underflow.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/fp31_forget_underflow.rs rename to engine/crates/layerfs-daemon/tests/fp31_forget_underflow.rs diff --git a/core/crates/layerfs-daemon/tests/host_handoff.rs b/engine/crates/layerfs-daemon/tests/host_handoff.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/host_handoff.rs rename to engine/crates/layerfs-daemon/tests/host_handoff.rs diff --git a/core/crates/layerfs-daemon/tests/host_install.rs b/engine/crates/layerfs-daemon/tests/host_install.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/host_install.rs rename to engine/crates/layerfs-daemon/tests/host_install.rs diff --git a/core/crates/layerfs-daemon/tests/installed_store.rs b/engine/crates/layerfs-daemon/tests/installed_store.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/installed_store.rs rename to engine/crates/layerfs-daemon/tests/installed_store.rs diff --git a/core/crates/layerfs-daemon/tests/kernel_coherence.rs b/engine/crates/layerfs-daemon/tests/kernel_coherence.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/kernel_coherence.rs rename to engine/crates/layerfs-daemon/tests/kernel_coherence.rs diff --git a/core/crates/layerfs-daemon/tests/kernel_custody.rs b/engine/crates/layerfs-daemon/tests/kernel_custody.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/kernel_custody.rs rename to engine/crates/layerfs-daemon/tests/kernel_custody.rs diff --git a/core/crates/layerfs-daemon/tests/kernel_mount.rs b/engine/crates/layerfs-daemon/tests/kernel_mount.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/kernel_mount.rs rename to engine/crates/layerfs-daemon/tests/kernel_mount.rs diff --git a/core/crates/layerfs-daemon/tests/kernel_mutation.rs b/engine/crates/layerfs-daemon/tests/kernel_mutation.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/kernel_mutation.rs rename to engine/crates/layerfs-daemon/tests/kernel_mutation.rs diff --git a/core/crates/layerfs-daemon/tests/mounted_commit.rs b/engine/crates/layerfs-daemon/tests/mounted_commit.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/mounted_commit.rs rename to engine/crates/layerfs-daemon/tests/mounted_commit.rs diff --git a/core/crates/layerfs-daemon/tests/mounted_commit_failures.rs b/engine/crates/layerfs-daemon/tests/mounted_commit_failures.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/mounted_commit_failures.rs rename to engine/crates/layerfs-daemon/tests/mounted_commit_failures.rs diff --git a/core/crates/layerfs-daemon/tests/mounted_concurrency.rs b/engine/crates/layerfs-daemon/tests/mounted_concurrency.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/mounted_concurrency.rs rename to engine/crates/layerfs-daemon/tests/mounted_concurrency.rs diff --git a/core/crates/layerfs-daemon/tests/mounted_cycles.rs b/engine/crates/layerfs-daemon/tests/mounted_cycles.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/mounted_cycles.rs rename to engine/crates/layerfs-daemon/tests/mounted_cycles.rs diff --git a/core/crates/layerfs-daemon/tests/mounted_drain.rs b/engine/crates/layerfs-daemon/tests/mounted_drain.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/mounted_drain.rs rename to engine/crates/layerfs-daemon/tests/mounted_drain.rs diff --git a/core/crates/layerfs-daemon/tests/mounted_execute.rs b/engine/crates/layerfs-daemon/tests/mounted_execute.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/mounted_execute.rs rename to engine/crates/layerfs-daemon/tests/mounted_execute.rs diff --git a/core/crates/layerfs-daemon/tests/mounted_failure_scope.rs b/engine/crates/layerfs-daemon/tests/mounted_failure_scope.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/mounted_failure_scope.rs rename to engine/crates/layerfs-daemon/tests/mounted_failure_scope.rs diff --git a/core/crates/layerfs-daemon/tests/mounted_fusectl.rs b/engine/crates/layerfs-daemon/tests/mounted_fusectl.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/mounted_fusectl.rs rename to engine/crates/layerfs-daemon/tests/mounted_fusectl.rs diff --git a/core/crates/layerfs-daemon/tests/mounted_install.rs b/engine/crates/layerfs-daemon/tests/mounted_install.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/mounted_install.rs rename to engine/crates/layerfs-daemon/tests/mounted_install.rs diff --git a/core/crates/layerfs-daemon/tests/mounted_links.rs b/engine/crates/layerfs-daemon/tests/mounted_links.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/mounted_links.rs rename to engine/crates/layerfs-daemon/tests/mounted_links.rs diff --git a/core/crates/layerfs-daemon/tests/mounted_listing_reads.rs b/engine/crates/layerfs-daemon/tests/mounted_listing_reads.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/mounted_listing_reads.rs rename to engine/crates/layerfs-daemon/tests/mounted_listing_reads.rs diff --git a/core/crates/layerfs-daemon/tests/mounted_low_water.rs b/engine/crates/layerfs-daemon/tests/mounted_low_water.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/mounted_low_water.rs rename to engine/crates/layerfs-daemon/tests/mounted_low_water.rs diff --git a/core/crates/layerfs-daemon/tests/mounted_parallel_commits.rs b/engine/crates/layerfs-daemon/tests/mounted_parallel_commits.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/mounted_parallel_commits.rs rename to engine/crates/layerfs-daemon/tests/mounted_parallel_commits.rs diff --git a/core/crates/layerfs-daemon/tests/mounted_patterns.rs b/engine/crates/layerfs-daemon/tests/mounted_patterns.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/mounted_patterns.rs rename to engine/crates/layerfs-daemon/tests/mounted_patterns.rs diff --git a/core/crates/layerfs-daemon/tests/mounted_recognizer.rs b/engine/crates/layerfs-daemon/tests/mounted_recognizer.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/mounted_recognizer.rs rename to engine/crates/layerfs-daemon/tests/mounted_recognizer.rs diff --git a/core/crates/layerfs-daemon/tests/mounted_rewind.rs b/engine/crates/layerfs-daemon/tests/mounted_rewind.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/mounted_rewind.rs rename to engine/crates/layerfs-daemon/tests/mounted_rewind.rs diff --git a/core/crates/layerfs-daemon/tests/mounted_serial_admission.rs b/engine/crates/layerfs-daemon/tests/mounted_serial_admission.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/mounted_serial_admission.rs rename to engine/crates/layerfs-daemon/tests/mounted_serial_admission.rs diff --git a/core/crates/layerfs-daemon/tests/mounted_sqlite_full.rs b/engine/crates/layerfs-daemon/tests/mounted_sqlite_full.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/mounted_sqlite_full.rs rename to engine/crates/layerfs-daemon/tests/mounted_sqlite_full.rs diff --git a/core/crates/layerfs-daemon/tests/mounted_store_read.rs b/engine/crates/layerfs-daemon/tests/mounted_store_read.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/mounted_store_read.rs rename to engine/crates/layerfs-daemon/tests/mounted_store_read.rs diff --git a/core/crates/layerfs-daemon/tests/negative_entries.rs b/engine/crates/layerfs-daemon/tests/negative_entries.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/negative_entries.rs rename to engine/crates/layerfs-daemon/tests/negative_entries.rs diff --git a/core/crates/layerfs-daemon/tests/r5_10_producer_profile.rs b/engine/crates/layerfs-daemon/tests/r5_10_producer_profile.rs similarity index 99% rename from core/crates/layerfs-daemon/tests/r5_10_producer_profile.rs rename to engine/crates/layerfs-daemon/tests/r5_10_producer_profile.rs index 1cec415e9..f86d39cfe 100644 --- a/core/crates/layerfs-daemon/tests/r5_10_producer_profile.rs +++ b/engine/crates/layerfs-daemon/tests/r5_10_producer_profile.rs @@ -23,7 +23,7 @@ //! read-back that session made when it opened. //! //! `LAYERFS_CONSTRUCTION_WORKERS` is not read by any file under -//! `core/crates/*/src`; nothing here can make it select anything. The bound +//! `engine/crates/*/src`; nothing here can make it select anything. The bound //! shown is the one the product has by construction. //! //! One test: the thread count is a process-wide observation. @@ -483,7 +483,7 @@ fn r5_10_each_mounted_commit_has_one_producer_on_the_one_open_disposable_writer_ quiet(&harness, ready.token); harness.unmount(&ready); println!( - "{name} RESULT commits={} mounts=2 producers_per_commit=1 store=one_arc_never_dropped session=one_writable_never_sealed_or_reopened profile=Disposable/wal/synchronous=0 durable=NOT_RUN composing_calls={:?} LAYERFS_CONSTRUCTION_WORKERS=not_read_by_core/crates/*/src", + "{name} RESULT commits={} mounts=2 producers_per_commit=1 store=one_arc_never_dropped session=one_writable_never_sealed_or_reopened profile=Disposable/wal/synchronous=0 durable=NOT_RUN composing_calls={:?} LAYERFS_CONSTRUCTION_WORKERS=not_read_by_engine/crates/*/src", records.len(), composing.iter().map(|seen| seen.port).collect::>() ); diff --git a/core/crates/layerfs-daemon/tests/r5_5_install_survival.rs b/engine/crates/layerfs-daemon/tests/r5_5_install_survival.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/r5_5_install_survival.rs rename to engine/crates/layerfs-daemon/tests/r5_5_install_survival.rs diff --git a/core/crates/layerfs-daemon/tests/r5_9_dirty_mapping.rs b/engine/crates/layerfs-daemon/tests/r5_9_dirty_mapping.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/r5_9_dirty_mapping.rs rename to engine/crates/layerfs-daemon/tests/r5_9_dirty_mapping.rs diff --git a/core/crates/layerfs-daemon/tests/rename_predecessor.rs b/engine/crates/layerfs-daemon/tests/rename_predecessor.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/rename_predecessor.rs rename to engine/crates/layerfs-daemon/tests/rename_predecessor.rs diff --git a/core/crates/layerfs-daemon/tests/shared_cache_pressure.rs b/engine/crates/layerfs-daemon/tests/shared_cache_pressure.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/shared_cache_pressure.rs rename to engine/crates/layerfs-daemon/tests/shared_cache_pressure.rs diff --git a/core/crates/layerfs-daemon/tests/store_commit.rs b/engine/crates/layerfs-daemon/tests/store_commit.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/store_commit.rs rename to engine/crates/layerfs-daemon/tests/store_commit.rs diff --git a/core/crates/layerfs-daemon/tests/store_reader_lifecycle.rs b/engine/crates/layerfs-daemon/tests/store_reader_lifecycle.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/store_reader_lifecycle.rs rename to engine/crates/layerfs-daemon/tests/store_reader_lifecycle.rs diff --git a/core/crates/layerfs-daemon/tests/support/captured_drive.rs b/engine/crates/layerfs-daemon/tests/support/captured_drive.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/support/captured_drive.rs rename to engine/crates/layerfs-daemon/tests/support/captured_drive.rs diff --git a/core/crates/layerfs-daemon/tests/support/complete_bytes.rs b/engine/crates/layerfs-daemon/tests/support/complete_bytes.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/support/complete_bytes.rs rename to engine/crates/layerfs-daemon/tests/support/complete_bytes.rs diff --git a/core/crates/layerfs-daemon/tests/support/complete_fixture.rs b/engine/crates/layerfs-daemon/tests/support/complete_fixture.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/support/complete_fixture.rs rename to engine/crates/layerfs-daemon/tests/support/complete_fixture.rs diff --git a/core/crates/layerfs-daemon/tests/support/complete_oracle.rs b/engine/crates/layerfs-daemon/tests/support/complete_oracle.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/support/complete_oracle.rs rename to engine/crates/layerfs-daemon/tests/support/complete_oracle.rs diff --git a/core/crates/layerfs-daemon/tests/support/control_fixture.rs b/engine/crates/layerfs-daemon/tests/support/control_fixture.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/support/control_fixture.rs rename to engine/crates/layerfs-daemon/tests/support/control_fixture.rs diff --git a/core/crates/layerfs-daemon/tests/support/delete_trace.rs b/engine/crates/layerfs-daemon/tests/support/delete_trace.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/support/delete_trace.rs rename to engine/crates/layerfs-daemon/tests/support/delete_trace.rs diff --git a/core/crates/layerfs-daemon/tests/support/fusectl.rs b/engine/crates/layerfs-daemon/tests/support/fusectl.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/support/fusectl.rs rename to engine/crates/layerfs-daemon/tests/support/fusectl.rs diff --git a/core/crates/layerfs-daemon/tests/support/held_writer.rs b/engine/crates/layerfs-daemon/tests/support/held_writer.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/support/held_writer.rs rename to engine/crates/layerfs-daemon/tests/support/held_writer.rs diff --git a/core/crates/layerfs-daemon/tests/support/history_boundary.rs b/engine/crates/layerfs-daemon/tests/support/history_boundary.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/support/history_boundary.rs rename to engine/crates/layerfs-daemon/tests/support/history_boundary.rs diff --git a/core/crates/layerfs-daemon/tests/support/history_gate.rs b/engine/crates/layerfs-daemon/tests/support/history_gate.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/support/history_gate.rs rename to engine/crates/layerfs-daemon/tests/support/history_gate.rs diff --git a/core/crates/layerfs-daemon/tests/support/holds.rs b/engine/crates/layerfs-daemon/tests/support/holds.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/support/holds.rs rename to engine/crates/layerfs-daemon/tests/support/holds.rs diff --git a/core/crates/layerfs-daemon/tests/support/host_install.rs b/engine/crates/layerfs-daemon/tests/support/host_install.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/support/host_install.rs rename to engine/crates/layerfs-daemon/tests/support/host_install.rs diff --git a/core/crates/layerfs-daemon/tests/support/install_docker.rs b/engine/crates/layerfs-daemon/tests/support/install_docker.rs similarity index 97% rename from core/crates/layerfs-daemon/tests/support/install_docker.rs rename to engine/crates/layerfs-daemon/tests/support/install_docker.rs index f706daf52..c0afc8174 100644 --- a/core/crates/layerfs-daemon/tests/support/install_docker.rs +++ b/engine/crates/layerfs-daemon/tests/support/install_docker.rs @@ -43,9 +43,7 @@ impl Daemon { let volume = format!("{name}-store"); let binary = std::env::var("LAYERFS_INSTALL_DAEMON_BINARY") .expect("explicit build-listed Linux binary"); - assert!( - binary.starts_with("/work/core/target/issue320/linux-test/debug/deps/host_handoff-") - ); + assert!(binary.starts_with("/work/target/issue320/linux-test/debug/deps/host_handoff-")); let absent = docker(&["volume", "inspect", &volume]); assert!( !absent.status.success() diff --git a/core/crates/layerfs-daemon/tests/support/installed_store.rs b/engine/crates/layerfs-daemon/tests/support/installed_store.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/support/installed_store.rs rename to engine/crates/layerfs-daemon/tests/support/installed_store.rs diff --git a/core/crates/layerfs-daemon/tests/support/long_branch_rig.rs b/engine/crates/layerfs-daemon/tests/support/long_branch_rig.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/support/long_branch_rig.rs rename to engine/crates/layerfs-daemon/tests/support/long_branch_rig.rs diff --git a/core/crates/layerfs-daemon/tests/support/mounted.rs b/engine/crates/layerfs-daemon/tests/support/mounted.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/support/mounted.rs rename to engine/crates/layerfs-daemon/tests/support/mounted.rs diff --git a/core/crates/layerfs-daemon/tests/support/mounted_commit.rs b/engine/crates/layerfs-daemon/tests/support/mounted_commit.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/support/mounted_commit.rs rename to engine/crates/layerfs-daemon/tests/support/mounted_commit.rs diff --git a/core/crates/layerfs-daemon/tests/support/mutating.rs b/engine/crates/layerfs-daemon/tests/support/mutating.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/support/mutating.rs rename to engine/crates/layerfs-daemon/tests/support/mutating.rs diff --git a/core/crates/layerfs-daemon/tests/support/namespace_model.rs b/engine/crates/layerfs-daemon/tests/support/namespace_model.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/support/namespace_model.rs rename to engine/crates/layerfs-daemon/tests/support/namespace_model.rs diff --git a/core/crates/layerfs-daemon/tests/support/record_counts.rs b/engine/crates/layerfs-daemon/tests/support/record_counts.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/support/record_counts.rs rename to engine/crates/layerfs-daemon/tests/support/record_counts.rs diff --git a/core/crates/layerfs-daemon/tests/support/request_path.rs b/engine/crates/layerfs-daemon/tests/support/request_path.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/support/request_path.rs rename to engine/crates/layerfs-daemon/tests/support/request_path.rs diff --git a/core/crates/layerfs-daemon/tests/support/request_path_counts/c01.txt b/engine/crates/layerfs-daemon/tests/support/request_path_counts/c01.txt similarity index 100% rename from core/crates/layerfs-daemon/tests/support/request_path_counts/c01.txt rename to engine/crates/layerfs-daemon/tests/support/request_path_counts/c01.txt diff --git a/core/crates/layerfs-daemon/tests/support/request_path_counts/c03.txt b/engine/crates/layerfs-daemon/tests/support/request_path_counts/c03.txt similarity index 100% rename from core/crates/layerfs-daemon/tests/support/request_path_counts/c03.txt rename to engine/crates/layerfs-daemon/tests/support/request_path_counts/c03.txt diff --git a/core/crates/layerfs-daemon/tests/support/request_path_counts/c04.txt b/engine/crates/layerfs-daemon/tests/support/request_path_counts/c04.txt similarity index 100% rename from core/crates/layerfs-daemon/tests/support/request_path_counts/c04.txt rename to engine/crates/layerfs-daemon/tests/support/request_path_counts/c04.txt diff --git a/core/crates/layerfs-daemon/tests/support/request_path_counts/c06.txt b/engine/crates/layerfs-daemon/tests/support/request_path_counts/c06.txt similarity index 100% rename from core/crates/layerfs-daemon/tests/support/request_path_counts/c06.txt rename to engine/crates/layerfs-daemon/tests/support/request_path_counts/c06.txt diff --git a/core/crates/layerfs-daemon/tests/support/request_path_counts/c10.txt b/engine/crates/layerfs-daemon/tests/support/request_path_counts/c10.txt similarity index 100% rename from core/crates/layerfs-daemon/tests/support/request_path_counts/c10.txt rename to engine/crates/layerfs-daemon/tests/support/request_path_counts/c10.txt diff --git a/core/crates/layerfs-daemon/tests/support/shared_cache_rig.rs b/engine/crates/layerfs-daemon/tests/support/shared_cache_rig.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/support/shared_cache_rig.rs rename to engine/crates/layerfs-daemon/tests/support/shared_cache_rig.rs diff --git a/core/crates/layerfs-daemon/tests/support/statement_trace.rs b/engine/crates/layerfs-daemon/tests/support/statement_trace.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/support/statement_trace.rs rename to engine/crates/layerfs-daemon/tests/support/statement_trace.rs diff --git a/core/crates/layerfs-daemon/tests/support/store_gate.rs b/engine/crates/layerfs-daemon/tests/support/store_gate.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/support/store_gate.rs rename to engine/crates/layerfs-daemon/tests/support/store_gate.rs diff --git a/core/crates/layerfs-daemon/tests/telemetry_recording.rs b/engine/crates/layerfs-daemon/tests/telemetry_recording.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/telemetry_recording.rs rename to engine/crates/layerfs-daemon/tests/telemetry_recording.rs diff --git a/core/crates/layerfs-daemon/tests/workspace_databases.rs b/engine/crates/layerfs-daemon/tests/workspace_databases.rs similarity index 100% rename from core/crates/layerfs-daemon/tests/workspace_databases.rs rename to engine/crates/layerfs-daemon/tests/workspace_databases.rs diff --git a/core/crates/layerfs-fuse/Cargo.toml b/engine/crates/layerfs-fuse/Cargo.toml similarity index 88% rename from core/crates/layerfs-fuse/Cargo.toml rename to engine/crates/layerfs-fuse/Cargo.toml index 100948008..01eaa178e 100644 --- a/core/crates/layerfs-fuse/Cargo.toml +++ b/engine/crates/layerfs-fuse/Cargo.toml @@ -9,7 +9,7 @@ license.workspace = true [dependencies] layerfs-overlay = { path = "../layerfs-overlay" } layerfs-workspace = { path = "../layerfs-workspace" } -layerfs-content = { path = "../layerfs-content" } +layerfs-content = { path = "../../../core/crates/layerfs-content" } [target.'cfg(target_os = "linux")'.dependencies] fuser = { version = "=0.18.0", default-features = false } diff --git a/core/crates/layerfs-fuse/src/attributes.rs b/engine/crates/layerfs-fuse/src/attributes.rs similarity index 100% rename from core/crates/layerfs-fuse/src/attributes.rs rename to engine/crates/layerfs-fuse/src/attributes.rs diff --git a/core/crates/layerfs-fuse/src/coherence/attributes.rs b/engine/crates/layerfs-fuse/src/coherence/attributes.rs similarity index 100% rename from core/crates/layerfs-fuse/src/coherence/attributes.rs rename to engine/crates/layerfs-fuse/src/coherence/attributes.rs diff --git a/core/crates/layerfs-fuse/src/coherence/mod.rs b/engine/crates/layerfs-fuse/src/coherence/mod.rs similarity index 100% rename from core/crates/layerfs-fuse/src/coherence/mod.rs rename to engine/crates/layerfs-fuse/src/coherence/mod.rs diff --git a/core/crates/layerfs-fuse/src/coherence/pages.rs b/engine/crates/layerfs-fuse/src/coherence/pages.rs similarity index 100% rename from core/crates/layerfs-fuse/src/coherence/pages.rs rename to engine/crates/layerfs-fuse/src/coherence/pages.rs diff --git a/core/crates/layerfs-fuse/src/coherence/reply_order.rs b/engine/crates/layerfs-fuse/src/coherence/reply_order.rs similarity index 100% rename from core/crates/layerfs-fuse/src/coherence/reply_order.rs rename to engine/crates/layerfs-fuse/src/coherence/reply_order.rs diff --git a/core/crates/layerfs-fuse/src/dispatch/diagnostics.rs b/engine/crates/layerfs-fuse/src/dispatch/diagnostics.rs similarity index 100% rename from core/crates/layerfs-fuse/src/dispatch/diagnostics.rs rename to engine/crates/layerfs-fuse/src/dispatch/diagnostics.rs diff --git a/core/crates/layerfs-fuse/src/dispatch/mod.rs b/engine/crates/layerfs-fuse/src/dispatch/mod.rs similarity index 100% rename from core/crates/layerfs-fuse/src/dispatch/mod.rs rename to engine/crates/layerfs-fuse/src/dispatch/mod.rs diff --git a/core/crates/layerfs-fuse/src/dispatch/requests.rs b/engine/crates/layerfs-fuse/src/dispatch/requests.rs similarity index 100% rename from core/crates/layerfs-fuse/src/dispatch/requests.rs rename to engine/crates/layerfs-fuse/src/dispatch/requests.rs diff --git a/core/crates/layerfs-fuse/src/dispatch/types.rs b/engine/crates/layerfs-fuse/src/dispatch/types.rs similarity index 100% rename from core/crates/layerfs-fuse/src/dispatch/types.rs rename to engine/crates/layerfs-fuse/src/dispatch/types.rs diff --git a/core/crates/layerfs-fuse/src/lib.rs b/engine/crates/layerfs-fuse/src/lib.rs similarity index 100% rename from core/crates/layerfs-fuse/src/lib.rs rename to engine/crates/layerfs-fuse/src/lib.rs diff --git a/core/crates/layerfs-fuse/src/mount/mod.rs b/engine/crates/layerfs-fuse/src/mount/mod.rs similarity index 100% rename from core/crates/layerfs-fuse/src/mount/mod.rs rename to engine/crates/layerfs-fuse/src/mount/mod.rs diff --git a/core/crates/layerfs-fuse/src/mount/profile.rs b/engine/crates/layerfs-fuse/src/mount/profile.rs similarity index 100% rename from core/crates/layerfs-fuse/src/mount/profile.rs rename to engine/crates/layerfs-fuse/src/mount/profile.rs diff --git a/core/crates/layerfs-fuse/src/mount/syscalls.rs b/engine/crates/layerfs-fuse/src/mount/syscalls.rs similarity index 100% rename from core/crates/layerfs-fuse/src/mount/syscalls.rs rename to engine/crates/layerfs-fuse/src/mount/syscalls.rs diff --git a/core/crates/layerfs-fuse/src/operations/create.rs b/engine/crates/layerfs-fuse/src/operations/create.rs similarity index 100% rename from core/crates/layerfs-fuse/src/operations/create.rs rename to engine/crates/layerfs-fuse/src/operations/create.rs diff --git a/core/crates/layerfs-fuse/src/operations/directory.rs b/engine/crates/layerfs-fuse/src/operations/directory.rs similarity index 100% rename from core/crates/layerfs-fuse/src/operations/directory.rs rename to engine/crates/layerfs-fuse/src/operations/directory.rs diff --git a/core/crates/layerfs-fuse/src/operations/flush.rs b/engine/crates/layerfs-fuse/src/operations/flush.rs similarity index 100% rename from core/crates/layerfs-fuse/src/operations/flush.rs rename to engine/crates/layerfs-fuse/src/operations/flush.rs diff --git a/core/crates/layerfs-fuse/src/operations/link.rs b/engine/crates/layerfs-fuse/src/operations/link.rs similarity index 100% rename from core/crates/layerfs-fuse/src/operations/link.rs rename to engine/crates/layerfs-fuse/src/operations/link.rs diff --git a/core/crates/layerfs-fuse/src/operations/lookup.rs b/engine/crates/layerfs-fuse/src/operations/lookup.rs similarity index 100% rename from core/crates/layerfs-fuse/src/operations/lookup.rs rename to engine/crates/layerfs-fuse/src/operations/lookup.rs diff --git a/core/crates/layerfs-fuse/src/operations/mod.rs b/engine/crates/layerfs-fuse/src/operations/mod.rs similarity index 100% rename from core/crates/layerfs-fuse/src/operations/mod.rs rename to engine/crates/layerfs-fuse/src/operations/mod.rs diff --git a/core/crates/layerfs-fuse/src/operations/mutation.rs b/engine/crates/layerfs-fuse/src/operations/mutation.rs similarity index 100% rename from core/crates/layerfs-fuse/src/operations/mutation.rs rename to engine/crates/layerfs-fuse/src/operations/mutation.rs diff --git a/core/crates/layerfs-fuse/src/operations/read.rs b/engine/crates/layerfs-fuse/src/operations/read.rs similarity index 100% rename from core/crates/layerfs-fuse/src/operations/read.rs rename to engine/crates/layerfs-fuse/src/operations/read.rs diff --git a/core/crates/layerfs-fuse/src/operations/remove.rs b/engine/crates/layerfs-fuse/src/operations/remove.rs similarity index 100% rename from core/crates/layerfs-fuse/src/operations/remove.rs rename to engine/crates/layerfs-fuse/src/operations/remove.rs diff --git a/core/crates/layerfs-fuse/src/operations/rename.rs b/engine/crates/layerfs-fuse/src/operations/rename.rs similarity index 100% rename from core/crates/layerfs-fuse/src/operations/rename.rs rename to engine/crates/layerfs-fuse/src/operations/rename.rs diff --git a/core/crates/layerfs-fuse/src/operations/unsupported.rs b/engine/crates/layerfs-fuse/src/operations/unsupported.rs similarity index 100% rename from core/crates/layerfs-fuse/src/operations/unsupported.rs rename to engine/crates/layerfs-fuse/src/operations/unsupported.rs diff --git a/core/crates/layerfs-fuse/src/operations/write.rs b/engine/crates/layerfs-fuse/src/operations/write.rs similarity index 100% rename from core/crates/layerfs-fuse/src/operations/write.rs rename to engine/crates/layerfs-fuse/src/operations/write.rs diff --git a/core/crates/layerfs-fuse/src/phase.rs b/engine/crates/layerfs-fuse/src/phase.rs similarity index 100% rename from core/crates/layerfs-fuse/src/phase.rs rename to engine/crates/layerfs-fuse/src/phase.rs diff --git a/core/crates/layerfs-fuse/src/ports.rs b/engine/crates/layerfs-fuse/src/ports.rs similarity index 100% rename from core/crates/layerfs-fuse/src/ports.rs rename to engine/crates/layerfs-fuse/src/ports.rs diff --git a/core/crates/layerfs-fuse/src/request/accounting.rs b/engine/crates/layerfs-fuse/src/request/accounting.rs similarity index 100% rename from core/crates/layerfs-fuse/src/request/accounting.rs rename to engine/crates/layerfs-fuse/src/request/accounting.rs diff --git a/core/crates/layerfs-fuse/src/request/callbacks.rs b/engine/crates/layerfs-fuse/src/request/callbacks.rs similarity index 100% rename from core/crates/layerfs-fuse/src/request/callbacks.rs rename to engine/crates/layerfs-fuse/src/request/callbacks.rs diff --git a/core/crates/layerfs-fuse/src/request/directory.rs b/engine/crates/layerfs-fuse/src/request/directory.rs similarity index 100% rename from core/crates/layerfs-fuse/src/request/directory.rs rename to engine/crates/layerfs-fuse/src/request/directory.rs diff --git a/core/crates/layerfs-fuse/src/request/failure.rs b/engine/crates/layerfs-fuse/src/request/failure.rs similarity index 100% rename from core/crates/layerfs-fuse/src/request/failure.rs rename to engine/crates/layerfs-fuse/src/request/failure.rs diff --git a/core/crates/layerfs-fuse/src/request/inline.rs b/engine/crates/layerfs-fuse/src/request/inline.rs similarity index 100% rename from core/crates/layerfs-fuse/src/request/inline.rs rename to engine/crates/layerfs-fuse/src/request/inline.rs diff --git a/core/crates/layerfs-fuse/src/request/mod.rs b/engine/crates/layerfs-fuse/src/request/mod.rs similarity index 100% rename from core/crates/layerfs-fuse/src/request/mod.rs rename to engine/crates/layerfs-fuse/src/request/mod.rs diff --git a/core/crates/layerfs-fuse/src/request/mutate.rs b/engine/crates/layerfs-fuse/src/request/mutate.rs similarity index 100% rename from core/crates/layerfs-fuse/src/request/mutate.rs rename to engine/crates/layerfs-fuse/src/request/mutate.rs diff --git a/core/crates/layerfs-fuse/src/request/reply.rs b/engine/crates/layerfs-fuse/src/request/reply.rs similarity index 100% rename from core/crates/layerfs-fuse/src/request/reply.rs rename to engine/crates/layerfs-fuse/src/request/reply.rs diff --git a/core/crates/layerfs-fuse/src/request/state.rs b/engine/crates/layerfs-fuse/src/request/state.rs similarity index 100% rename from core/crates/layerfs-fuse/src/request/state.rs rename to engine/crates/layerfs-fuse/src/request/state.rs diff --git a/core/crates/layerfs-fuse/src/request/terminal.rs b/engine/crates/layerfs-fuse/src/request/terminal.rs similarity index 100% rename from core/crates/layerfs-fuse/src/request/terminal.rs rename to engine/crates/layerfs-fuse/src/request/terminal.rs diff --git a/core/crates/layerfs-fuse/src/session/drain.rs b/engine/crates/layerfs-fuse/src/session/drain.rs similarity index 100% rename from core/crates/layerfs-fuse/src/session/drain.rs rename to engine/crates/layerfs-fuse/src/session/drain.rs diff --git a/core/crates/layerfs-fuse/src/session/force.rs b/engine/crates/layerfs-fuse/src/session/force.rs similarity index 100% rename from core/crates/layerfs-fuse/src/session/force.rs rename to engine/crates/layerfs-fuse/src/session/force.rs diff --git a/core/crates/layerfs-fuse/src/session/invalidate.rs b/engine/crates/layerfs-fuse/src/session/invalidate.rs similarity index 100% rename from core/crates/layerfs-fuse/src/session/invalidate.rs rename to engine/crates/layerfs-fuse/src/session/invalidate.rs diff --git a/core/crates/layerfs-fuse/src/session/mod.rs b/engine/crates/layerfs-fuse/src/session/mod.rs similarity index 100% rename from core/crates/layerfs-fuse/src/session/mod.rs rename to engine/crates/layerfs-fuse/src/session/mod.rs diff --git a/core/crates/layerfs-fuse/src/session/startup.rs b/engine/crates/layerfs-fuse/src/session/startup.rs similarity index 100% rename from core/crates/layerfs-fuse/src/session/startup.rs rename to engine/crates/layerfs-fuse/src/session/startup.rs diff --git a/core/crates/layerfs-fuse/src/session/state.rs b/engine/crates/layerfs-fuse/src/session/state.rs similarity index 100% rename from core/crates/layerfs-fuse/src/session/state.rs rename to engine/crates/layerfs-fuse/src/session/state.rs diff --git a/core/crates/layerfs-fuse/tests/attributes.rs b/engine/crates/layerfs-fuse/tests/attributes.rs similarity index 100% rename from core/crates/layerfs-fuse/tests/attributes.rs rename to engine/crates/layerfs-fuse/tests/attributes.rs diff --git a/core/crates/layerfs-fuse/tests/opcode_names.rs b/engine/crates/layerfs-fuse/tests/opcode_names.rs similarity index 100% rename from core/crates/layerfs-fuse/tests/opcode_names.rs rename to engine/crates/layerfs-fuse/tests/opcode_names.rs diff --git a/core/crates/layerfs-fuse/tests/opcode_time.rs b/engine/crates/layerfs-fuse/tests/opcode_time.rs similarity index 100% rename from core/crates/layerfs-fuse/tests/opcode_time.rs rename to engine/crates/layerfs-fuse/tests/opcode_time.rs diff --git a/core/crates/layerfs-fuse/tests/requests.rs b/engine/crates/layerfs-fuse/tests/requests.rs similarity index 100% rename from core/crates/layerfs-fuse/tests/requests.rs rename to engine/crates/layerfs-fuse/tests/requests.rs diff --git a/core/crates/layerfs-overlay/Cargo.toml b/engine/crates/layerfs-overlay/Cargo.toml similarity index 100% rename from core/crates/layerfs-overlay/Cargo.toml rename to engine/crates/layerfs-overlay/Cargo.toml diff --git a/core/crates/layerfs-overlay/examples/indexed_operation_record_profile.rs b/engine/crates/layerfs-overlay/examples/indexed_operation_record_profile.rs similarity index 100% rename from core/crates/layerfs-overlay/examples/indexed_operation_record_profile.rs rename to engine/crates/layerfs-overlay/examples/indexed_operation_record_profile.rs diff --git a/core/crates/layerfs-overlay/sql/schema.sql b/engine/crates/layerfs-overlay/sql/schema.sql similarity index 100% rename from core/crates/layerfs-overlay/sql/schema.sql rename to engine/crates/layerfs-overlay/sql/schema.sql diff --git a/core/crates/layerfs-overlay/src/contract/custody.rs b/engine/crates/layerfs-overlay/src/contract/custody.rs similarity index 100% rename from core/crates/layerfs-overlay/src/contract/custody.rs rename to engine/crates/layerfs-overlay/src/contract/custody.rs diff --git a/core/crates/layerfs-overlay/src/contract/error.rs b/engine/crates/layerfs-overlay/src/contract/error.rs similarity index 100% rename from core/crates/layerfs-overlay/src/contract/error.rs rename to engine/crates/layerfs-overlay/src/contract/error.rs diff --git a/core/crates/layerfs-overlay/src/contract/indexed_operation_record.rs b/engine/crates/layerfs-overlay/src/contract/indexed_operation_record.rs similarity index 100% rename from core/crates/layerfs-overlay/src/contract/indexed_operation_record.rs rename to engine/crates/layerfs-overlay/src/contract/indexed_operation_record.rs diff --git a/core/crates/layerfs-overlay/src/contract/kernel.rs b/engine/crates/layerfs-overlay/src/contract/kernel.rs similarity index 100% rename from core/crates/layerfs-overlay/src/contract/kernel.rs rename to engine/crates/layerfs-overlay/src/contract/kernel.rs diff --git a/core/crates/layerfs-overlay/src/contract/kernel_directory.rs b/engine/crates/layerfs-overlay/src/contract/kernel_directory.rs similarity index 100% rename from core/crates/layerfs-overlay/src/contract/kernel_directory.rs rename to engine/crates/layerfs-overlay/src/contract/kernel_directory.rs diff --git a/core/crates/layerfs-overlay/src/contract/mod.rs b/engine/crates/layerfs-overlay/src/contract/mod.rs similarity index 100% rename from core/crates/layerfs-overlay/src/contract/mod.rs rename to engine/crates/layerfs-overlay/src/contract/mod.rs diff --git a/core/crates/layerfs-overlay/src/contract/types.rs b/engine/crates/layerfs-overlay/src/contract/types.rs similarity index 100% rename from core/crates/layerfs-overlay/src/contract/types.rs rename to engine/crates/layerfs-overlay/src/contract/types.rs diff --git a/core/crates/layerfs-overlay/src/database/accounting.rs b/engine/crates/layerfs-overlay/src/database/accounting.rs similarity index 100% rename from core/crates/layerfs-overlay/src/database/accounting.rs rename to engine/crates/layerfs-overlay/src/database/accounting.rs diff --git a/core/crates/layerfs-overlay/src/database/connection.rs b/engine/crates/layerfs-overlay/src/database/connection.rs similarity index 100% rename from core/crates/layerfs-overlay/src/database/connection.rs rename to engine/crates/layerfs-overlay/src/database/connection.rs diff --git a/core/crates/layerfs-overlay/src/database/mod.rs b/engine/crates/layerfs-overlay/src/database/mod.rs similarity index 100% rename from core/crates/layerfs-overlay/src/database/mod.rs rename to engine/crates/layerfs-overlay/src/database/mod.rs diff --git a/core/crates/layerfs-overlay/src/database/physical.rs b/engine/crates/layerfs-overlay/src/database/physical.rs similarity index 100% rename from core/crates/layerfs-overlay/src/database/physical.rs rename to engine/crates/layerfs-overlay/src/database/physical.rs diff --git a/core/crates/layerfs-overlay/src/database/profile.rs b/engine/crates/layerfs-overlay/src/database/profile.rs similarity index 100% rename from core/crates/layerfs-overlay/src/database/profile.rs rename to engine/crates/layerfs-overlay/src/database/profile.rs diff --git a/core/crates/layerfs-overlay/src/database/startup.rs b/engine/crates/layerfs-overlay/src/database/startup.rs similarity index 100% rename from core/crates/layerfs-overlay/src/database/startup.rs rename to engine/crates/layerfs-overlay/src/database/startup.rs diff --git a/core/crates/layerfs-overlay/src/database/statements.rs b/engine/crates/layerfs-overlay/src/database/statements.rs similarity index 100% rename from core/crates/layerfs-overlay/src/database/statements.rs rename to engine/crates/layerfs-overlay/src/database/statements.rs diff --git a/core/crates/layerfs-overlay/src/diagnostics/indexed_operation_record_plan.rs b/engine/crates/layerfs-overlay/src/diagnostics/indexed_operation_record_plan.rs similarity index 100% rename from core/crates/layerfs-overlay/src/diagnostics/indexed_operation_record_plan.rs rename to engine/crates/layerfs-overlay/src/diagnostics/indexed_operation_record_plan.rs diff --git a/core/crates/layerfs-overlay/src/diagnostics/metrics.rs b/engine/crates/layerfs-overlay/src/diagnostics/metrics.rs similarity index 100% rename from core/crates/layerfs-overlay/src/diagnostics/metrics.rs rename to engine/crates/layerfs-overlay/src/diagnostics/metrics.rs diff --git a/core/crates/layerfs-overlay/src/diagnostics/mod.rs b/engine/crates/layerfs-overlay/src/diagnostics/mod.rs similarity index 100% rename from core/crates/layerfs-overlay/src/diagnostics/mod.rs rename to engine/crates/layerfs-overlay/src/diagnostics/mod.rs diff --git a/core/crates/layerfs-overlay/src/diagnostics/payload.rs b/engine/crates/layerfs-overlay/src/diagnostics/payload.rs similarity index 100% rename from core/crates/layerfs-overlay/src/diagnostics/payload.rs rename to engine/crates/layerfs-overlay/src/diagnostics/payload.rs diff --git a/core/crates/layerfs-overlay/src/diagnostics/startup.rs b/engine/crates/layerfs-overlay/src/diagnostics/startup.rs similarity index 100% rename from core/crates/layerfs-overlay/src/diagnostics/startup.rs rename to engine/crates/layerfs-overlay/src/diagnostics/startup.rs diff --git a/core/crates/layerfs-overlay/src/lib.rs b/engine/crates/layerfs-overlay/src/lib.rs similarity index 100% rename from core/crates/layerfs-overlay/src/lib.rs rename to engine/crates/layerfs-overlay/src/lib.rs diff --git a/core/crates/layerfs-overlay/src/lifetime/captured_reader.rs b/engine/crates/layerfs-overlay/src/lifetime/captured_reader.rs similarity index 100% rename from core/crates/layerfs-overlay/src/lifetime/captured_reader.rs rename to engine/crates/layerfs-overlay/src/lifetime/captured_reader.rs diff --git a/core/crates/layerfs-overlay/src/lifetime/close.rs b/engine/crates/layerfs-overlay/src/lifetime/close.rs similarity index 100% rename from core/crates/layerfs-overlay/src/lifetime/close.rs rename to engine/crates/layerfs-overlay/src/lifetime/close.rs diff --git a/core/crates/layerfs-overlay/src/lifetime/composition.rs b/engine/crates/layerfs-overlay/src/lifetime/composition.rs similarity index 100% rename from core/crates/layerfs-overlay/src/lifetime/composition.rs rename to engine/crates/layerfs-overlay/src/lifetime/composition.rs diff --git a/core/crates/layerfs-overlay/src/lifetime/file_owners.rs b/engine/crates/layerfs-overlay/src/lifetime/file_owners.rs similarity index 100% rename from core/crates/layerfs-overlay/src/lifetime/file_owners.rs rename to engine/crates/layerfs-overlay/src/lifetime/file_owners.rs diff --git a/core/crates/layerfs-overlay/src/lifetime/frontier.rs b/engine/crates/layerfs-overlay/src/lifetime/frontier.rs similarity index 100% rename from core/crates/layerfs-overlay/src/lifetime/frontier.rs rename to engine/crates/layerfs-overlay/src/lifetime/frontier.rs diff --git a/core/crates/layerfs-overlay/src/lifetime/generation.rs b/engine/crates/layerfs-overlay/src/lifetime/generation.rs similarity index 100% rename from core/crates/layerfs-overlay/src/lifetime/generation.rs rename to engine/crates/layerfs-overlay/src/lifetime/generation.rs diff --git a/core/crates/layerfs-overlay/src/lifetime/indexed_operation_record.rs b/engine/crates/layerfs-overlay/src/lifetime/indexed_operation_record.rs similarity index 100% rename from core/crates/layerfs-overlay/src/lifetime/indexed_operation_record.rs rename to engine/crates/layerfs-overlay/src/lifetime/indexed_operation_record.rs diff --git a/core/crates/layerfs-overlay/src/lifetime/kernel.rs b/engine/crates/layerfs-overlay/src/lifetime/kernel.rs similarity index 100% rename from core/crates/layerfs-overlay/src/lifetime/kernel.rs rename to engine/crates/layerfs-overlay/src/lifetime/kernel.rs diff --git a/core/crates/layerfs-overlay/src/lifetime/kernel_cookie.rs b/engine/crates/layerfs-overlay/src/lifetime/kernel_cookie.rs similarity index 100% rename from core/crates/layerfs-overlay/src/lifetime/kernel_cookie.rs rename to engine/crates/layerfs-overlay/src/lifetime/kernel_cookie.rs diff --git a/core/crates/layerfs-overlay/src/lifetime/kernel_directory.rs b/engine/crates/layerfs-overlay/src/lifetime/kernel_directory.rs similarity index 100% rename from core/crates/layerfs-overlay/src/lifetime/kernel_directory.rs rename to engine/crates/layerfs-overlay/src/lifetime/kernel_directory.rs diff --git a/core/crates/layerfs-overlay/src/lifetime/kernel_directory_read.rs b/engine/crates/layerfs-overlay/src/lifetime/kernel_directory_read.rs similarity index 100% rename from core/crates/layerfs-overlay/src/lifetime/kernel_directory_read.rs rename to engine/crates/layerfs-overlay/src/lifetime/kernel_directory_read.rs diff --git a/core/crates/layerfs-overlay/src/lifetime/kernel_file.rs b/engine/crates/layerfs-overlay/src/lifetime/kernel_file.rs similarity index 100% rename from core/crates/layerfs-overlay/src/lifetime/kernel_file.rs rename to engine/crates/layerfs-overlay/src/lifetime/kernel_file.rs diff --git a/core/crates/layerfs-overlay/src/lifetime/kernel_mutation.rs b/engine/crates/layerfs-overlay/src/lifetime/kernel_mutation.rs similarity index 100% rename from core/crates/layerfs-overlay/src/lifetime/kernel_mutation.rs rename to engine/crates/layerfs-overlay/src/lifetime/kernel_mutation.rs diff --git a/core/crates/layerfs-overlay/src/lifetime/kernel_visit.rs b/engine/crates/layerfs-overlay/src/lifetime/kernel_visit.rs similarity index 100% rename from core/crates/layerfs-overlay/src/lifetime/kernel_visit.rs rename to engine/crates/layerfs-overlay/src/lifetime/kernel_visit.rs diff --git a/core/crates/layerfs-overlay/src/lifetime/lookup.rs b/engine/crates/layerfs-overlay/src/lifetime/lookup.rs similarity index 100% rename from core/crates/layerfs-overlay/src/lifetime/lookup.rs rename to engine/crates/layerfs-overlay/src/lifetime/lookup.rs diff --git a/core/crates/layerfs-overlay/src/lifetime/mod.rs b/engine/crates/layerfs-overlay/src/lifetime/mod.rs similarity index 100% rename from core/crates/layerfs-overlay/src/lifetime/mod.rs rename to engine/crates/layerfs-overlay/src/lifetime/mod.rs diff --git a/core/crates/layerfs-overlay/src/lifetime/operation.rs b/engine/crates/layerfs-overlay/src/lifetime/operation.rs similarity index 100% rename from core/crates/layerfs-overlay/src/lifetime/operation.rs rename to engine/crates/layerfs-overlay/src/lifetime/operation.rs diff --git a/core/crates/layerfs-overlay/src/lifetime/orphan.rs b/engine/crates/layerfs-overlay/src/lifetime/orphan.rs similarity index 100% rename from core/crates/layerfs-overlay/src/lifetime/orphan.rs rename to engine/crates/layerfs-overlay/src/lifetime/orphan.rs diff --git a/core/crates/layerfs-overlay/src/lifetime/source.rs b/engine/crates/layerfs-overlay/src/lifetime/source.rs similarity index 100% rename from core/crates/layerfs-overlay/src/lifetime/source.rs rename to engine/crates/layerfs-overlay/src/lifetime/source.rs diff --git a/core/crates/layerfs-overlay/src/lifetime/tickets.rs b/engine/crates/layerfs-overlay/src/lifetime/tickets.rs similarity index 100% rename from core/crates/layerfs-overlay/src/lifetime/tickets.rs rename to engine/crates/layerfs-overlay/src/lifetime/tickets.rs diff --git a/core/crates/layerfs-overlay/src/lifetime/workspace.rs b/engine/crates/layerfs-overlay/src/lifetime/workspace.rs similarity index 100% rename from core/crates/layerfs-overlay/src/lifetime/workspace.rs rename to engine/crates/layerfs-overlay/src/lifetime/workspace.rs diff --git a/core/crates/layerfs-overlay/src/maintenance/garbage.rs b/engine/crates/layerfs-overlay/src/maintenance/garbage.rs similarity index 100% rename from core/crates/layerfs-overlay/src/maintenance/garbage.rs rename to engine/crates/layerfs-overlay/src/maintenance/garbage.rs diff --git a/core/crates/layerfs-overlay/src/maintenance/indexed_operation_record.rs b/engine/crates/layerfs-overlay/src/maintenance/indexed_operation_record.rs similarity index 100% rename from core/crates/layerfs-overlay/src/maintenance/indexed_operation_record.rs rename to engine/crates/layerfs-overlay/src/maintenance/indexed_operation_record.rs diff --git a/core/crates/layerfs-overlay/src/maintenance/mod.rs b/engine/crates/layerfs-overlay/src/maintenance/mod.rs similarity index 100% rename from core/crates/layerfs-overlay/src/maintenance/mod.rs rename to engine/crates/layerfs-overlay/src/maintenance/mod.rs diff --git a/core/crates/layerfs-overlay/src/maintenance/orphan.rs b/engine/crates/layerfs-overlay/src/maintenance/orphan.rs similarity index 100% rename from core/crates/layerfs-overlay/src/maintenance/orphan.rs rename to engine/crates/layerfs-overlay/src/maintenance/orphan.rs diff --git a/core/crates/layerfs-overlay/src/maintenance/pieces.rs b/engine/crates/layerfs-overlay/src/maintenance/pieces.rs similarity index 100% rename from core/crates/layerfs-overlay/src/maintenance/pieces.rs rename to engine/crates/layerfs-overlay/src/maintenance/pieces.rs diff --git a/core/crates/layerfs-overlay/src/maintenance/ready.rs b/engine/crates/layerfs-overlay/src/maintenance/ready.rs similarity index 100% rename from core/crates/layerfs-overlay/src/maintenance/ready.rs rename to engine/crates/layerfs-overlay/src/maintenance/ready.rs diff --git a/core/crates/layerfs-overlay/src/maintenance/source_wait.rs b/engine/crates/layerfs-overlay/src/maintenance/source_wait.rs similarity index 100% rename from core/crates/layerfs-overlay/src/maintenance/source_wait.rs rename to engine/crates/layerfs-overlay/src/maintenance/source_wait.rs diff --git a/core/crates/layerfs-overlay/src/maintenance/work.rs b/engine/crates/layerfs-overlay/src/maintenance/work.rs similarity index 100% rename from core/crates/layerfs-overlay/src/maintenance/work.rs rename to engine/crates/layerfs-overlay/src/maintenance/work.rs diff --git a/core/crates/layerfs-overlay/src/namespace/captured_namespace.rs b/engine/crates/layerfs-overlay/src/namespace/captured_namespace.rs similarity index 100% rename from core/crates/layerfs-overlay/src/namespace/captured_namespace.rs rename to engine/crates/layerfs-overlay/src/namespace/captured_namespace.rs diff --git a/core/crates/layerfs-overlay/src/namespace/compound.rs b/engine/crates/layerfs-overlay/src/namespace/compound.rs similarity index 100% rename from core/crates/layerfs-overlay/src/namespace/compound.rs rename to engine/crates/layerfs-overlay/src/namespace/compound.rs diff --git a/core/crates/layerfs-overlay/src/namespace/directory_entry.rs b/engine/crates/layerfs-overlay/src/namespace/directory_entry.rs similarity index 100% rename from core/crates/layerfs-overlay/src/namespace/directory_entry.rs rename to engine/crates/layerfs-overlay/src/namespace/directory_entry.rs diff --git a/core/crates/layerfs-overlay/src/namespace/inode.rs b/engine/crates/layerfs-overlay/src/namespace/inode.rs similarity index 100% rename from core/crates/layerfs-overlay/src/namespace/inode.rs rename to engine/crates/layerfs-overlay/src/namespace/inode.rs diff --git a/core/crates/layerfs-overlay/src/namespace/job_rows.rs b/engine/crates/layerfs-overlay/src/namespace/job_rows.rs similarity index 100% rename from core/crates/layerfs-overlay/src/namespace/job_rows.rs rename to engine/crates/layerfs-overlay/src/namespace/job_rows.rs diff --git a/core/crates/layerfs-overlay/src/namespace/mod.rs b/engine/crates/layerfs-overlay/src/namespace/mod.rs similarity index 100% rename from core/crates/layerfs-overlay/src/namespace/mod.rs rename to engine/crates/layerfs-overlay/src/namespace/mod.rs diff --git a/core/crates/layerfs-overlay/src/namespace/predecessor.rs b/engine/crates/layerfs-overlay/src/namespace/predecessor.rs similarity index 100% rename from core/crates/layerfs-overlay/src/namespace/predecessor.rs rename to engine/crates/layerfs-overlay/src/namespace/predecessor.rs diff --git a/core/crates/layerfs-overlay/src/open/counts.rs b/engine/crates/layerfs-overlay/src/open/counts.rs similarity index 100% rename from core/crates/layerfs-overlay/src/open/counts.rs rename to engine/crates/layerfs-overlay/src/open/counts.rs diff --git a/core/crates/layerfs-overlay/src/open/directories.rs b/engine/crates/layerfs-overlay/src/open/directories.rs similarity index 100% rename from core/crates/layerfs-overlay/src/open/directories.rs rename to engine/crates/layerfs-overlay/src/open/directories.rs diff --git a/core/crates/layerfs-overlay/src/open/files.rs b/engine/crates/layerfs-overlay/src/open/files.rs similarity index 100% rename from core/crates/layerfs-overlay/src/open/files.rs rename to engine/crates/layerfs-overlay/src/open/files.rs diff --git a/core/crates/layerfs-overlay/src/open/journal.rs b/engine/crates/layerfs-overlay/src/open/journal.rs similarity index 100% rename from core/crates/layerfs-overlay/src/open/journal.rs rename to engine/crates/layerfs-overlay/src/open/journal.rs diff --git a/core/crates/layerfs-overlay/src/open/kernel.rs b/engine/crates/layerfs-overlay/src/open/kernel.rs similarity index 100% rename from core/crates/layerfs-overlay/src/open/kernel.rs rename to engine/crates/layerfs-overlay/src/open/kernel.rs diff --git a/core/crates/layerfs-overlay/src/open/mod.rs b/engine/crates/layerfs-overlay/src/open/mod.rs similarity index 100% rename from core/crates/layerfs-overlay/src/open/mod.rs rename to engine/crates/layerfs-overlay/src/open/mod.rs diff --git a/core/crates/layerfs-overlay/src/payload/access.rs b/engine/crates/layerfs-overlay/src/payload/access.rs similarity index 100% rename from core/crates/layerfs-overlay/src/payload/access.rs rename to engine/crates/layerfs-overlay/src/payload/access.rs diff --git a/core/crates/layerfs-overlay/src/payload/captured_runs.rs b/engine/crates/layerfs-overlay/src/payload/captured_runs.rs similarity index 100% rename from core/crates/layerfs-overlay/src/payload/captured_runs.rs rename to engine/crates/layerfs-overlay/src/payload/captured_runs.rs diff --git a/core/crates/layerfs-overlay/src/payload/captured_types.rs b/engine/crates/layerfs-overlay/src/payload/captured_types.rs similarity index 100% rename from core/crates/layerfs-overlay/src/payload/captured_types.rs rename to engine/crates/layerfs-overlay/src/payload/captured_types.rs diff --git a/core/crates/layerfs-overlay/src/payload/cells.rs b/engine/crates/layerfs-overlay/src/payload/cells.rs similarity index 100% rename from core/crates/layerfs-overlay/src/payload/cells.rs rename to engine/crates/layerfs-overlay/src/payload/cells.rs diff --git a/core/crates/layerfs-overlay/src/payload/digest.rs b/engine/crates/layerfs-overlay/src/payload/digest.rs similarity index 100% rename from core/crates/layerfs-overlay/src/payload/digest.rs rename to engine/crates/layerfs-overlay/src/payload/digest.rs diff --git a/core/crates/layerfs-overlay/src/payload/layers.rs b/engine/crates/layerfs-overlay/src/payload/layers.rs similarity index 100% rename from core/crates/layerfs-overlay/src/payload/layers.rs rename to engine/crates/layerfs-overlay/src/payload/layers.rs diff --git a/core/crates/layerfs-overlay/src/payload/mod.rs b/engine/crates/layerfs-overlay/src/payload/mod.rs similarity index 100% rename from core/crates/layerfs-overlay/src/payload/mod.rs rename to engine/crates/layerfs-overlay/src/payload/mod.rs diff --git a/core/crates/layerfs-overlay/src/payload/pieces/captured.rs b/engine/crates/layerfs-overlay/src/payload/pieces/captured.rs similarity index 100% rename from core/crates/layerfs-overlay/src/payload/pieces/captured.rs rename to engine/crates/layerfs-overlay/src/payload/pieces/captured.rs diff --git a/core/crates/layerfs-overlay/src/payload/pieces/mod.rs b/engine/crates/layerfs-overlay/src/payload/pieces/mod.rs similarity index 100% rename from core/crates/layerfs-overlay/src/payload/pieces/mod.rs rename to engine/crates/layerfs-overlay/src/payload/pieces/mod.rs diff --git a/core/crates/layerfs-overlay/src/payload/pieces/moves.rs b/engine/crates/layerfs-overlay/src/payload/pieces/moves.rs similarity index 100% rename from core/crates/layerfs-overlay/src/payload/pieces/moves.rs rename to engine/crates/layerfs-overlay/src/payload/pieces/moves.rs diff --git a/core/crates/layerfs-overlay/src/payload/pieces/rows.rs b/engine/crates/layerfs-overlay/src/payload/pieces/rows.rs similarity index 100% rename from core/crates/layerfs-overlay/src/payload/pieces/rows.rs rename to engine/crates/layerfs-overlay/src/payload/pieces/rows.rs diff --git a/core/crates/layerfs-overlay/src/payload/runs.rs b/engine/crates/layerfs-overlay/src/payload/runs.rs similarity index 100% rename from core/crates/layerfs-overlay/src/payload/runs.rs rename to engine/crates/layerfs-overlay/src/payload/runs.rs diff --git a/core/crates/layerfs-overlay/src/payload/stream.rs b/engine/crates/layerfs-overlay/src/payload/stream.rs similarity index 100% rename from core/crates/layerfs-overlay/src/payload/stream.rs rename to engine/crates/layerfs-overlay/src/payload/stream.rs diff --git a/core/crates/layerfs-overlay/tests/allocation_filesystem.rs b/engine/crates/layerfs-overlay/tests/allocation_filesystem.rs similarity index 100% rename from core/crates/layerfs-overlay/tests/allocation_filesystem.rs rename to engine/crates/layerfs-overlay/tests/allocation_filesystem.rs diff --git a/core/crates/layerfs-overlay/tests/captured_namespace.rs b/engine/crates/layerfs-overlay/tests/captured_namespace.rs similarity index 100% rename from core/crates/layerfs-overlay/tests/captured_namespace.rs rename to engine/crates/layerfs-overlay/tests/captured_namespace.rs diff --git a/core/crates/layerfs-overlay/tests/captured_runs.rs b/engine/crates/layerfs-overlay/tests/captured_runs.rs similarity index 100% rename from core/crates/layerfs-overlay/tests/captured_runs.rs rename to engine/crates/layerfs-overlay/tests/captured_runs.rs diff --git a/core/crates/layerfs-overlay/tests/device_fixture.sh b/engine/crates/layerfs-overlay/tests/device_fixture.sh similarity index 86% rename from core/crates/layerfs-overlay/tests/device_fixture.sh rename to engine/crates/layerfs-overlay/tests/device_fixture.sh index efb03b827..9cf99769d 100644 --- a/core/crates/layerfs-overlay/tests/device_fixture.sh +++ b/engine/crates/layerfs-overlay/tests/device_fixture.sh @@ -37,9 +37,9 @@ proof_test=${2:-$proof_default} if [ "${3:-}" = ioerr ]; then [ "$proof_binary" != device_capacity ] || [ "$proof_package" = layerfs-overlay ] proof_shim=$proof_root/enospc-as-eio.so - cc -shared -fPIC -Wall -Wextra -Werror core/crates/layerfs-overlay/tests/enospc_as_eio.c -ldl -o "$proof_shim" + cc -shared -fPIC -Wall -Wextra -Werror engine/crates/layerfs-overlay/tests/enospc_as_eio.c -ldl -o "$proof_shim" export LAYERFS_PROOF_TRANSLATE_ENOSPC=1 export LD_PRELOAD=$proof_shim fi -timeout --signal=KILL 90 cargo test --manifest-path core/Cargo.toml --locked --offline -p "$proof_package" --test "$proof_binary" "$proof_test" -- --exact --ignored --nocapture --test-threads=1 +timeout --signal=KILL 90 cargo test --manifest-path Cargo.toml --locked --offline -p "$proof_package" --test "$proof_binary" "$proof_test" -- --exact --ignored --nocapture --test-threads=1 printf 'OWNED PROOF COMPLETED; normal teardown follows\n' diff --git a/core/crates/layerfs-overlay/tests/digests.rs b/engine/crates/layerfs-overlay/tests/digests.rs similarity index 100% rename from core/crates/layerfs-overlay/tests/digests.rs rename to engine/crates/layerfs-overlay/tests/digests.rs diff --git a/core/crates/layerfs-overlay/tests/enospc_as_eio.c b/engine/crates/layerfs-overlay/tests/enospc_as_eio.c similarity index 100% rename from core/crates/layerfs-overlay/tests/enospc_as_eio.c rename to engine/crates/layerfs-overlay/tests/enospc_as_eio.c diff --git a/core/crates/layerfs-overlay/tests/error_identity.rs b/engine/crates/layerfs-overlay/tests/error_identity.rs similarity index 100% rename from core/crates/layerfs-overlay/tests/error_identity.rs rename to engine/crates/layerfs-overlay/tests/error_identity.rs diff --git a/core/crates/layerfs-overlay/tests/indexed_operation_record.rs b/engine/crates/layerfs-overlay/tests/indexed_operation_record.rs similarity index 100% rename from core/crates/layerfs-overlay/tests/indexed_operation_record.rs rename to engine/crates/layerfs-overlay/tests/indexed_operation_record.rs diff --git a/core/crates/layerfs-overlay/tests/indexed_operation_record_cursor.rs b/engine/crates/layerfs-overlay/tests/indexed_operation_record_cursor.rs similarity index 100% rename from core/crates/layerfs-overlay/tests/indexed_operation_record_cursor.rs rename to engine/crates/layerfs-overlay/tests/indexed_operation_record_cursor.rs diff --git a/core/crates/layerfs-overlay/tests/indexed_operation_record_entries.rs b/engine/crates/layerfs-overlay/tests/indexed_operation_record_entries.rs similarity index 100% rename from core/crates/layerfs-overlay/tests/indexed_operation_record_entries.rs rename to engine/crates/layerfs-overlay/tests/indexed_operation_record_entries.rs diff --git a/core/crates/layerfs-overlay/tests/kept_live.rs b/engine/crates/layerfs-overlay/tests/kept_live.rs similarity index 100% rename from core/crates/layerfs-overlay/tests/kept_live.rs rename to engine/crates/layerfs-overlay/tests/kept_live.rs diff --git a/core/crates/layerfs-overlay/tests/kernel_memory.rs b/engine/crates/layerfs-overlay/tests/kernel_memory.rs similarity index 100% rename from core/crates/layerfs-overlay/tests/kernel_memory.rs rename to engine/crates/layerfs-overlay/tests/kernel_memory.rs diff --git a/core/crates/layerfs-overlay/tests/orphans.rs b/engine/crates/layerfs-overlay/tests/orphans.rs similarity index 100% rename from core/crates/layerfs-overlay/tests/orphans.rs rename to engine/crates/layerfs-overlay/tests/orphans.rs diff --git a/core/crates/layerfs-overlay/tests/payload.rs b/engine/crates/layerfs-overlay/tests/payload.rs similarity index 100% rename from core/crates/layerfs-overlay/tests/payload.rs rename to engine/crates/layerfs-overlay/tests/payload.rs diff --git a/core/crates/layerfs-overlay/tests/payload_runs.rs b/engine/crates/layerfs-overlay/tests/payload_runs.rs similarity index 100% rename from core/crates/layerfs-overlay/tests/payload_runs.rs rename to engine/crates/layerfs-overlay/tests/payload_runs.rs diff --git a/core/crates/layerfs-overlay/tests/payload_support/mod.rs b/engine/crates/layerfs-overlay/tests/payload_support/mod.rs similarity index 100% rename from core/crates/layerfs-overlay/tests/payload_support/mod.rs rename to engine/crates/layerfs-overlay/tests/payload_support/mod.rs diff --git a/core/crates/layerfs-overlay/tests/piece_lifetimes.rs b/engine/crates/layerfs-overlay/tests/piece_lifetimes.rs similarity index 100% rename from core/crates/layerfs-overlay/tests/piece_lifetimes.rs rename to engine/crates/layerfs-overlay/tests/piece_lifetimes.rs diff --git a/core/crates/layerfs-overlay/tests/pieces.rs b/engine/crates/layerfs-overlay/tests/pieces.rs similarity index 100% rename from core/crates/layerfs-overlay/tests/pieces.rs rename to engine/crates/layerfs-overlay/tests/pieces.rs diff --git a/core/crates/layerfs-persistence/Cargo.toml b/engine/crates/layerfs-persistence/Cargo.toml similarity index 72% rename from core/crates/layerfs-persistence/Cargo.toml rename to engine/crates/layerfs-persistence/Cargo.toml index 8a34236d2..747630e70 100644 --- a/core/crates/layerfs-persistence/Cargo.toml +++ b/engine/crates/layerfs-persistence/Cargo.toml @@ -7,10 +7,10 @@ rust-version.workspace = true license.workspace = true [dependencies] -layerfs-storage = { path = "../layerfs-storage" } -layerfs-history = { path = "../layerfs-history", default-features = false } -layerfs-content = { path = "../layerfs-content" } -layerfs-telemetry = { path = "../layerfs-telemetry" } +layerfs-storage = { path = "../../../core/crates/layerfs-storage" } +layerfs-history = { path = "../../../core/crates/layerfs-history", default-features = false } +layerfs-content = { path = "../../../core/crates/layerfs-content" } +layerfs-telemetry = { path = "../../../core/crates/layerfs-telemetry" } rusqlite = { version = "=0.40.2", features = ["cache", "limits", "blob"] } [dev-dependencies] diff --git a/core/crates/layerfs-persistence/README.md b/engine/crates/layerfs-persistence/README.md similarity index 100% rename from core/crates/layerfs-persistence/README.md rename to engine/crates/layerfs-persistence/README.md diff --git a/core/crates/layerfs-persistence/examples/explain_reservation.rs b/engine/crates/layerfs-persistence/examples/explain_reservation.rs similarity index 100% rename from core/crates/layerfs-persistence/examples/explain_reservation.rs rename to engine/crates/layerfs-persistence/examples/explain_reservation.rs diff --git a/core/crates/layerfs-persistence/examples/issue327_counters_v2.rs b/engine/crates/layerfs-persistence/examples/issue327_counters_v2.rs similarity index 100% rename from core/crates/layerfs-persistence/examples/issue327_counters_v2.rs rename to engine/crates/layerfs-persistence/examples/issue327_counters_v2.rs diff --git a/core/crates/layerfs-persistence/examples/issue327_counters_v3.rs b/engine/crates/layerfs-persistence/examples/issue327_counters_v3.rs similarity index 100% rename from core/crates/layerfs-persistence/examples/issue327_counters_v3.rs rename to engine/crates/layerfs-persistence/examples/issue327_counters_v3.rs diff --git a/core/crates/layerfs-persistence/examples/issue327_counters_v4.rs b/engine/crates/layerfs-persistence/examples/issue327_counters_v4.rs similarity index 100% rename from core/crates/layerfs-persistence/examples/issue327_counters_v4.rs rename to engine/crates/layerfs-persistence/examples/issue327_counters_v4.rs diff --git a/core/crates/layerfs-persistence/examples/issue327_counters_v5.rs b/engine/crates/layerfs-persistence/examples/issue327_counters_v5.rs similarity index 100% rename from core/crates/layerfs-persistence/examples/issue327_counters_v5.rs rename to engine/crates/layerfs-persistence/examples/issue327_counters_v5.rs diff --git a/core/crates/layerfs-persistence/examples/issue327_readonly_diagnostic.rs b/engine/crates/layerfs-persistence/examples/issue327_readonly_diagnostic.rs similarity index 100% rename from core/crates/layerfs-persistence/examples/issue327_readonly_diagnostic.rs rename to engine/crates/layerfs-persistence/examples/issue327_readonly_diagnostic.rs diff --git a/core/crates/layerfs-persistence/examples/metadata_allocation_probe.rs b/engine/crates/layerfs-persistence/examples/metadata_allocation_probe.rs similarity index 100% rename from core/crates/layerfs-persistence/examples/metadata_allocation_probe.rs rename to engine/crates/layerfs-persistence/examples/metadata_allocation_probe.rs diff --git a/core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/abandoned.sql b/engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/abandoned.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/abandoned.sql rename to engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/abandoned.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/advance.sql b/engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/advance.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/advance.sql rename to engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/advance.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/begin.sql b/engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/begin.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/begin.sql rename to engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/begin.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/bind_host_file.sql b/engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/bind_host_file.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/bind_host_file.sql rename to engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/bind_host_file.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/bindings_first.sql b/engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/bindings_first.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/bindings_first.sql rename to engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/bindings_first.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/bindings_next.sql b/engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/bindings_next.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/bindings_next.sql rename to engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/bindings_next.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/charge.sql b/engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/charge.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/charge.sql rename to engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/charge.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/claim_epoch.sql b/engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/claim_epoch.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/claim_epoch.sql rename to engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/claim_epoch.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/complete_file.sql b/engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/complete_file.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/complete_file.sql rename to engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/complete_file.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/credit.sql b/engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/credit.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/credit.sql rename to engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/credit.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/directories.sql b/engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/directories.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/directories.sql rename to engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/directories.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/directory_path.sql b/engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/directory_path.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/directory_path.sql rename to engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/directory_path.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/directory_sizes.sql b/engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/directory_sizes.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/directory_sizes.sql rename to engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/directory_sizes.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/discard_entries.sql b/engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/discard_entries.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/discard_entries.sql rename to engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/discard_entries.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/discard_entry_keys.sql b/engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/discard_entry_keys.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/discard_entry_keys.sql rename to engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/discard_entry_keys.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/discard_entry_tail.sql b/engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/discard_entry_tail.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/discard_entry_tail.sql rename to engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/discard_entry_tail.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/discard_host_file.sql b/engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/discard_host_file.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/discard_host_file.sql rename to engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/discard_host_file.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/discard_host_file_keys.sql b/engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/discard_host_file_keys.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/discard_host_file_keys.sql rename to engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/discard_host_file_keys.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/discard_host_file_tail.sql b/engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/discard_host_file_tail.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/discard_host_file_tail.sql rename to engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/discard_host_file_tail.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/entries_first.sql b/engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/entries_first.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/entries_first.sql rename to engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/entries_first.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/entries_next.sql b/engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/entries_next.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/entries_next.sql rename to engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/entries_next.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/entry_dependencies.sql b/engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/entry_dependencies.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/entry_dependencies.sql rename to engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/entry_dependencies.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/file_roots.sql b/engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/file_roots.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/file_roots.sql rename to engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/file_roots.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/job.sql b/engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/job.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/job.sql rename to engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/job.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/job_sizes.sql b/engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/job_sizes.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/job_sizes.sql rename to engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/job_sizes.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/jobs.sql b/engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/jobs.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/jobs.sql rename to engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/jobs.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/owner.sql b/engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/owner.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/owner.sql rename to engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/owner.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/place_entry.sql b/engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/place_entry.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/place_entry.sql rename to engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/place_entry.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/put_entries.sql b/engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/put_entries.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/put_entries.sql rename to engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/put_entries.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/put_entry.sql b/engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/put_entry.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/put_entry.sql rename to engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/put_entry.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/put_host_file.sql b/engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/put_host_file.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/put_host_file.sql rename to engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/put_host_file.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/release.sql b/engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/release.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/release.sql rename to engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/release.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/release_abandoned.sql b/engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/release_abandoned.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/release_abandoned.sql rename to engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/release_abandoned.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/set_directory_root.sql b/engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/set_directory_root.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/set_directory_root.sql rename to engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/set_directory_root.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/unplaced_first.sql b/engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/unplaced_first.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/unplaced_first.sql rename to engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/unplaced_first.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/unplaced_next.sql b/engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/unplaced_next.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/acquisition/queries/unplaced_next.sql rename to engine/crates/layerfs-persistence/sql/sqlite/acquisition/queries/unplaced_next.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/acquisition/schema.sql b/engine/crates/layerfs-persistence/sql/sqlite/acquisition/schema.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/acquisition/schema.sql rename to engine/crates/layerfs-persistence/sql/sqlite/acquisition/schema.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/file_digest.sql b/engine/crates/layerfs-persistence/sql/sqlite/file_digest.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/file_digest.sql rename to engine/crates/layerfs-persistence/sql/sqlite/file_digest.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/history.sql b/engine/crates/layerfs-persistence/sql/sqlite/history.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/history.sql rename to engine/crates/layerfs-persistence/sql/sqlite/history.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/lineage.sql b/engine/crates/layerfs-persistence/sql/sqlite/lineage.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/lineage.sql rename to engine/crates/layerfs-persistence/sql/sqlite/lineage.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/merge_scratch.sql b/engine/crates/layerfs-persistence/sql/sqlite/merge_scratch.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/merge_scratch.sql rename to engine/crates/layerfs-persistence/sql/sqlite/merge_scratch.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/metadata.sql b/engine/crates/layerfs-persistence/sql/sqlite/metadata.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/metadata.sql rename to engine/crates/layerfs-persistence/sql/sqlite/metadata.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/objects.sql b/engine/crates/layerfs-persistence/sql/sqlite/objects.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/objects.sql rename to engine/crates/layerfs-persistence/sql/sqlite/objects.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/objects_units.sql b/engine/crates/layerfs-persistence/sql/sqlite/objects_units.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/objects_units.sql rename to engine/crates/layerfs-persistence/sql/sqlite/objects_units.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/objects_units_index.sql b/engine/crates/layerfs-persistence/sql/sqlite/objects_units_index.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/objects_units_index.sql rename to engine/crates/layerfs-persistence/sql/sqlite/objects_units_index.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/queries/history/allocation_advance_scope.sql b/engine/crates/layerfs-persistence/sql/sqlite/queries/history/allocation_advance_scope.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/queries/history/allocation_advance_scope.sql rename to engine/crates/layerfs-persistence/sql/sqlite/queries/history/allocation_advance_scope.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/queries/history/allocation_insert_scope.sql b/engine/crates/layerfs-persistence/sql/sqlite/queries/history/allocation_insert_scope.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/queries/history/allocation_insert_scope.sql rename to engine/crates/layerfs-persistence/sql/sqlite/queries/history/allocation_insert_scope.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/queries/history/allocation_scope_by_id.sql b/engine/crates/layerfs-persistence/sql/sqlite/queries/history/allocation_scope_by_id.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/queries/history/allocation_scope_by_id.sql rename to engine/crates/layerfs-persistence/sql/sqlite/queries/history/allocation_scope_by_id.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/queries/history/branch_branch_by_id.sql b/engine/crates/layerfs-persistence/sql/sqlite/queries/history/branch_branch_by_id.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/queries/history/branch_branch_by_id.sql rename to engine/crates/layerfs-persistence/sql/sqlite/queries/history/branch_branch_by_id.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/queries/history/branch_branch_by_name.sql b/engine/crates/layerfs-persistence/sql/sqlite/queries/history/branch_branch_by_name.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/queries/history/branch_branch_by_name.sql rename to engine/crates/layerfs-persistence/sql/sqlite/queries/history/branch_branch_by_name.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/queries/history/branch_branch_first_page.sql b/engine/crates/layerfs-persistence/sql/sqlite/queries/history/branch_branch_first_page.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/queries/history/branch_branch_first_page.sql rename to engine/crates/layerfs-persistence/sql/sqlite/queries/history/branch_branch_first_page.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/queries/history/branch_branch_name_taken.sql b/engine/crates/layerfs-persistence/sql/sqlite/queries/history/branch_branch_name_taken.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/queries/history/branch_branch_name_taken.sql rename to engine/crates/layerfs-persistence/sql/sqlite/queries/history/branch_branch_name_taken.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/queries/history/branch_branch_next_page.sql b/engine/crates/layerfs-persistence/sql/sqlite/queries/history/branch_branch_next_page.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/queries/history/branch_branch_next_page.sql rename to engine/crates/layerfs-persistence/sql/sqlite/queries/history/branch_branch_next_page.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/queries/history/branch_insert_branch.sql b/engine/crates/layerfs-persistence/sql/sqlite/queries/history/branch_insert_branch.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/queries/history/branch_insert_branch.sql rename to engine/crates/layerfs-persistence/sql/sqlite/queries/history/branch_insert_branch.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/queries/history/commit_advance_branch.sql b/engine/crates/layerfs-persistence/sql/sqlite/queries/history/commit_advance_branch.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/queries/history/commit_advance_branch.sql rename to engine/crates/layerfs-persistence/sql/sqlite/queries/history/commit_advance_branch.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/queries/history/commit_commit_by_id.sql b/engine/crates/layerfs-persistence/sql/sqlite/queries/history/commit_commit_by_id.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/queries/history/commit_commit_by_id.sql rename to engine/crates/layerfs-persistence/sql/sqlite/queries/history/commit_commit_by_id.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/queries/history/commit_insert_commit.sql b/engine/crates/layerfs-persistence/sql/sqlite/queries/history/commit_insert_commit.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/queries/history/commit_insert_commit.sql rename to engine/crates/layerfs-persistence/sql/sqlite/queries/history/commit_insert_commit.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/queries/history/digest_insert.sql b/engine/crates/layerfs-persistence/sql/sqlite/queries/history/digest_insert.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/queries/history/digest_insert.sql rename to engine/crates/layerfs-persistence/sql/sqlite/queries/history/digest_insert.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/queries/history/digest_of.sql b/engine/crates/layerfs-persistence/sql/sqlite/queries/history/digest_of.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/queries/history/digest_of.sql rename to engine/crates/layerfs-persistence/sql/sqlite/queries/history/digest_of.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/queries/history/hint_bindings_of.sql b/engine/crates/layerfs-persistence/sql/sqlite/queries/history/hint_bindings_of.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/queries/history/hint_bindings_of.sql rename to engine/crates/layerfs-persistence/sql/sqlite/queries/history/hint_bindings_of.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/queries/history/hint_insert_binding.sql b/engine/crates/layerfs-persistence/sql/sqlite/queries/history/hint_insert_binding.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/queries/history/hint_insert_binding.sql rename to engine/crates/layerfs-persistence/sql/sqlite/queries/history/hint_insert_binding.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_advance_stack.sql b/engine/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_advance_stack.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_advance_stack.sql rename to engine/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_advance_stack.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_insert_layer.sql b/engine/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_insert_layer.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_insert_layer.sql rename to engine/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_insert_layer.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_insert_stack.sql b/engine/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_insert_stack.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_insert_stack.sql rename to engine/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_insert_stack.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_layer_by_id.sql b/engine/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_layer_by_id.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_layer_by_id.sql rename to engine/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_layer_by_id.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_layer_by_source.sql b/engine/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_layer_by_source.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_layer_by_source.sql rename to engine/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_layer_by_source.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_layer_root.sql b/engine/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_layer_root.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_layer_root.sql rename to engine/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_layer_root.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_stack_by_id.sql b/engine/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_stack_by_id.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_stack_by_id.sql rename to engine/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_stack_by_id.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_stack_by_name.sql b/engine/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_stack_by_name.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_stack_by_name.sql rename to engine/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_stack_by_name.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_stack_first_page.sql b/engine/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_stack_first_page.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_stack_first_page.sql rename to engine/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_stack_first_page.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_stack_head.sql b/engine/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_stack_head.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_stack_head.sql rename to engine/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_stack_head.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_stack_name_taken.sql b/engine/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_stack_name_taken.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_stack_name_taken.sql rename to engine/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_stack_name_taken.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_stack_next_page.sql b/engine/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_stack_next_page.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_stack_next_page.sql rename to engine/crates/layerfs-persistence/sql/sqlite/queries/history/layerstack_stack_next_page.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_absorb.sql b/engine/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_absorb.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_absorb.sql rename to engine/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_absorb.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_absorbed_below.sql b/engine/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_absorbed_below.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_absorbed_below.sql rename to engine/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_absorbed_below.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_absorbed_height.sql b/engine/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_absorbed_height.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_absorbed_height.sql rename to engine/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_absorbed_height.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_commit.sql b/engine/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_commit.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_commit.sql rename to engine/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_commit.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_commit_at.sql b/engine/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_commit_at.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_commit_at.sql rename to engine/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_commit_at.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_insert_commit.sql b/engine/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_insert_commit.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_insert_commit.sql rename to engine/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_insert_commit.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_insert_layer.sql b/engine/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_insert_layer.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_insert_layer.sql rename to engine/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_insert_layer.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_layer.sql b/engine/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_layer.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_layer.sql rename to engine/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_layer.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_layers_above.sql b/engine/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_layers_above.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_layers_above.sql rename to engine/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_layers_above.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_merges.sql b/engine/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_merges.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_merges.sql rename to engine/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_merges.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_reach.sql b/engine/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_reach.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_reach.sql rename to engine/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_reach.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_reach_insert.sql b/engine/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_reach_insert.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_reach_insert.sql rename to engine/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_reach_insert.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_reach_prune.sql b/engine/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_reach_prune.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_reach_prune.sql rename to engine/crates/layerfs-persistence/sql/sqlite/queries/history/lineage_reach_prune.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/queries/history/statistics_record_init.sql b/engine/crates/layerfs-persistence/sql/sqlite/queries/history/statistics_record_init.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/queries/history/statistics_record_init.sql rename to engine/crates/layerfs-persistence/sql/sqlite/queries/history/statistics_record_init.sql diff --git a/core/crates/layerfs-persistence/sql/sqlite/queries/history/statistics_totals.sql b/engine/crates/layerfs-persistence/sql/sqlite/queries/history/statistics_totals.sql similarity index 100% rename from core/crates/layerfs-persistence/sql/sqlite/queries/history/statistics_totals.sql rename to engine/crates/layerfs-persistence/sql/sqlite/queries/history/statistics_totals.sql diff --git a/core/crates/layerfs-persistence/src/backend/mod.rs b/engine/crates/layerfs-persistence/src/backend/mod.rs similarity index 100% rename from core/crates/layerfs-persistence/src/backend/mod.rs rename to engine/crates/layerfs-persistence/src/backend/mod.rs diff --git a/core/crates/layerfs-persistence/src/backend/records.rs b/engine/crates/layerfs-persistence/src/backend/records.rs similarity index 100% rename from core/crates/layerfs-persistence/src/backend/records.rs rename to engine/crates/layerfs-persistence/src/backend/records.rs diff --git a/core/crates/layerfs-persistence/src/backend/sqlite/acquisition/accounting.rs b/engine/crates/layerfs-persistence/src/backend/sqlite/acquisition/accounting.rs similarity index 100% rename from core/crates/layerfs-persistence/src/backend/sqlite/acquisition/accounting.rs rename to engine/crates/layerfs-persistence/src/backend/sqlite/acquisition/accounting.rs diff --git a/core/crates/layerfs-persistence/src/backend/sqlite/acquisition/cleanup.rs b/engine/crates/layerfs-persistence/src/backend/sqlite/acquisition/cleanup.rs similarity index 100% rename from core/crates/layerfs-persistence/src/backend/sqlite/acquisition/cleanup.rs rename to engine/crates/layerfs-persistence/src/backend/sqlite/acquisition/cleanup.rs diff --git a/core/crates/layerfs-persistence/src/backend/sqlite/acquisition/entry_windows.rs b/engine/crates/layerfs-persistence/src/backend/sqlite/acquisition/entry_windows.rs similarity index 100% rename from core/crates/layerfs-persistence/src/backend/sqlite/acquisition/entry_windows.rs rename to engine/crates/layerfs-persistence/src/backend/sqlite/acquisition/entry_windows.rs diff --git a/core/crates/layerfs-persistence/src/backend/sqlite/acquisition/metadata.rs b/engine/crates/layerfs-persistence/src/backend/sqlite/acquisition/metadata.rs similarity index 100% rename from core/crates/layerfs-persistence/src/backend/sqlite/acquisition/metadata.rs rename to engine/crates/layerfs-persistence/src/backend/sqlite/acquisition/metadata.rs diff --git a/core/crates/layerfs-persistence/src/backend/sqlite/acquisition/mod.rs b/engine/crates/layerfs-persistence/src/backend/sqlite/acquisition/mod.rs similarity index 100% rename from core/crates/layerfs-persistence/src/backend/sqlite/acquisition/mod.rs rename to engine/crates/layerfs-persistence/src/backend/sqlite/acquisition/mod.rs diff --git a/core/crates/layerfs-persistence/src/backend/sqlite/acquisition/reads.rs b/engine/crates/layerfs-persistence/src/backend/sqlite/acquisition/reads.rs similarity index 100% rename from core/crates/layerfs-persistence/src/backend/sqlite/acquisition/reads.rs rename to engine/crates/layerfs-persistence/src/backend/sqlite/acquisition/reads.rs diff --git a/core/crates/layerfs-persistence/src/backend/sqlite/acquisition/root_windows.rs b/engine/crates/layerfs-persistence/src/backend/sqlite/acquisition/root_windows.rs similarity index 100% rename from core/crates/layerfs-persistence/src/backend/sqlite/acquisition/root_windows.rs rename to engine/crates/layerfs-persistence/src/backend/sqlite/acquisition/root_windows.rs diff --git a/core/crates/layerfs-persistence/src/backend/sqlite/acquisition/statements.rs b/engine/crates/layerfs-persistence/src/backend/sqlite/acquisition/statements.rs similarity index 100% rename from core/crates/layerfs-persistence/src/backend/sqlite/acquisition/statements.rs rename to engine/crates/layerfs-persistence/src/backend/sqlite/acquisition/statements.rs diff --git a/core/crates/layerfs-persistence/src/backend/sqlite/acquisition/writes.rs b/engine/crates/layerfs-persistence/src/backend/sqlite/acquisition/writes.rs similarity index 100% rename from core/crates/layerfs-persistence/src/backend/sqlite/acquisition/writes.rs rename to engine/crates/layerfs-persistence/src/backend/sqlite/acquisition/writes.rs diff --git a/core/crates/layerfs-persistence/src/backend/sqlite/admission.rs b/engine/crates/layerfs-persistence/src/backend/sqlite/admission.rs similarity index 100% rename from core/crates/layerfs-persistence/src/backend/sqlite/admission.rs rename to engine/crates/layerfs-persistence/src/backend/sqlite/admission.rs diff --git a/core/crates/layerfs-persistence/src/backend/sqlite/connection.rs b/engine/crates/layerfs-persistence/src/backend/sqlite/connection.rs similarity index 100% rename from core/crates/layerfs-persistence/src/backend/sqlite/connection.rs rename to engine/crates/layerfs-persistence/src/backend/sqlite/connection.rs diff --git a/core/crates/layerfs-persistence/src/backend/sqlite/file_control.rs b/engine/crates/layerfs-persistence/src/backend/sqlite/file_control.rs similarity index 100% rename from core/crates/layerfs-persistence/src/backend/sqlite/file_control.rs rename to engine/crates/layerfs-persistence/src/backend/sqlite/file_control.rs diff --git a/core/crates/layerfs-persistence/src/backend/sqlite/lane.rs b/engine/crates/layerfs-persistence/src/backend/sqlite/lane.rs similarity index 100% rename from core/crates/layerfs-persistence/src/backend/sqlite/lane.rs rename to engine/crates/layerfs-persistence/src/backend/sqlite/lane.rs diff --git a/core/crates/layerfs-persistence/src/backend/sqlite/metadata_allocation.rs b/engine/crates/layerfs-persistence/src/backend/sqlite/metadata_allocation.rs similarity index 100% rename from core/crates/layerfs-persistence/src/backend/sqlite/metadata_allocation.rs rename to engine/crates/layerfs-persistence/src/backend/sqlite/metadata_allocation.rs diff --git a/core/crates/layerfs-persistence/src/backend/sqlite/metadata_locations.rs b/engine/crates/layerfs-persistence/src/backend/sqlite/metadata_locations.rs similarity index 100% rename from core/crates/layerfs-persistence/src/backend/sqlite/metadata_locations.rs rename to engine/crates/layerfs-persistence/src/backend/sqlite/metadata_locations.rs diff --git a/core/crates/layerfs-persistence/src/backend/sqlite/metadata_policy.rs b/engine/crates/layerfs-persistence/src/backend/sqlite/metadata_policy.rs similarity index 100% rename from core/crates/layerfs-persistence/src/backend/sqlite/metadata_policy.rs rename to engine/crates/layerfs-persistence/src/backend/sqlite/metadata_policy.rs diff --git a/core/crates/layerfs-persistence/src/backend/sqlite/metadata_signatures.rs b/engine/crates/layerfs-persistence/src/backend/sqlite/metadata_signatures.rs similarity index 100% rename from core/crates/layerfs-persistence/src/backend/sqlite/metadata_signatures.rs rename to engine/crates/layerfs-persistence/src/backend/sqlite/metadata_signatures.rs diff --git a/core/crates/layerfs-persistence/src/backend/sqlite/metadata_values.rs b/engine/crates/layerfs-persistence/src/backend/sqlite/metadata_values.rs similarity index 100% rename from core/crates/layerfs-persistence/src/backend/sqlite/metadata_values.rs rename to engine/crates/layerfs-persistence/src/backend/sqlite/metadata_values.rs diff --git a/core/crates/layerfs-persistence/src/backend/sqlite/mod.rs b/engine/crates/layerfs-persistence/src/backend/sqlite/mod.rs similarity index 100% rename from core/crates/layerfs-persistence/src/backend/sqlite/mod.rs rename to engine/crates/layerfs-persistence/src/backend/sqlite/mod.rs diff --git a/core/crates/layerfs-persistence/src/backend/sqlite/objects_read.rs b/engine/crates/layerfs-persistence/src/backend/sqlite/objects_read.rs similarity index 100% rename from core/crates/layerfs-persistence/src/backend/sqlite/objects_read.rs rename to engine/crates/layerfs-persistence/src/backend/sqlite/objects_read.rs diff --git a/core/crates/layerfs-persistence/src/backend/sqlite/objects_selection.rs b/engine/crates/layerfs-persistence/src/backend/sqlite/objects_selection.rs similarity index 100% rename from core/crates/layerfs-persistence/src/backend/sqlite/objects_selection.rs rename to engine/crates/layerfs-persistence/src/backend/sqlite/objects_selection.rs diff --git a/core/crates/layerfs-persistence/src/backend/sqlite/prepared.rs b/engine/crates/layerfs-persistence/src/backend/sqlite/prepared.rs similarity index 100% rename from core/crates/layerfs-persistence/src/backend/sqlite/prepared.rs rename to engine/crates/layerfs-persistence/src/backend/sqlite/prepared.rs diff --git a/core/crates/layerfs-persistence/src/backend/sqlite/profile.rs b/engine/crates/layerfs-persistence/src/backend/sqlite/profile.rs similarity index 100% rename from core/crates/layerfs-persistence/src/backend/sqlite/profile.rs rename to engine/crates/layerfs-persistence/src/backend/sqlite/profile.rs diff --git a/core/crates/layerfs-persistence/src/backend/sqlite/publish.rs b/engine/crates/layerfs-persistence/src/backend/sqlite/publish.rs similarity index 100% rename from core/crates/layerfs-persistence/src/backend/sqlite/publish.rs rename to engine/crates/layerfs-persistence/src/backend/sqlite/publish.rs diff --git a/core/crates/layerfs-persistence/src/backend/sqlite/query.rs b/engine/crates/layerfs-persistence/src/backend/sqlite/query.rs similarity index 100% rename from core/crates/layerfs-persistence/src/backend/sqlite/query.rs rename to engine/crates/layerfs-persistence/src/backend/sqlite/query.rs diff --git a/core/crates/layerfs-persistence/src/backend/sqlite/reclamation.rs b/engine/crates/layerfs-persistence/src/backend/sqlite/reclamation.rs similarity index 100% rename from core/crates/layerfs-persistence/src/backend/sqlite/reclamation.rs rename to engine/crates/layerfs-persistence/src/backend/sqlite/reclamation.rs diff --git a/core/crates/layerfs-persistence/src/backend/sqlite/rows.rs b/engine/crates/layerfs-persistence/src/backend/sqlite/rows.rs similarity index 100% rename from core/crates/layerfs-persistence/src/backend/sqlite/rows.rs rename to engine/crates/layerfs-persistence/src/backend/sqlite/rows.rs diff --git a/core/crates/layerfs-persistence/src/backend/sqlite/schema.rs b/engine/crates/layerfs-persistence/src/backend/sqlite/schema.rs similarity index 100% rename from core/crates/layerfs-persistence/src/backend/sqlite/schema.rs rename to engine/crates/layerfs-persistence/src/backend/sqlite/schema.rs diff --git a/core/crates/layerfs-persistence/src/backend/sqlite/seal.rs b/engine/crates/layerfs-persistence/src/backend/sqlite/seal.rs similarity index 100% rename from core/crates/layerfs-persistence/src/backend/sqlite/seal.rs rename to engine/crates/layerfs-persistence/src/backend/sqlite/seal.rs diff --git a/core/crates/layerfs-persistence/src/backend/sqlite/seal_allocation.rs b/engine/crates/layerfs-persistence/src/backend/sqlite/seal_allocation.rs similarity index 100% rename from core/crates/layerfs-persistence/src/backend/sqlite/seal_allocation.rs rename to engine/crates/layerfs-persistence/src/backend/sqlite/seal_allocation.rs diff --git a/core/crates/layerfs-persistence/src/backend/sqlite/statement_work.rs b/engine/crates/layerfs-persistence/src/backend/sqlite/statement_work.rs similarity index 100% rename from core/crates/layerfs-persistence/src/backend/sqlite/statement_work.rs rename to engine/crates/layerfs-persistence/src/backend/sqlite/statement_work.rs diff --git a/core/crates/layerfs-persistence/src/backend/sqlite/thread_work.rs b/engine/crates/layerfs-persistence/src/backend/sqlite/thread_work.rs similarity index 100% rename from core/crates/layerfs-persistence/src/backend/sqlite/thread_work.rs rename to engine/crates/layerfs-persistence/src/backend/sqlite/thread_work.rs diff --git a/core/crates/layerfs-persistence/src/backend/sqlite/transaction.rs b/engine/crates/layerfs-persistence/src/backend/sqlite/transaction.rs similarity index 100% rename from core/crates/layerfs-persistence/src/backend/sqlite/transaction.rs rename to engine/crates/layerfs-persistence/src/backend/sqlite/transaction.rs diff --git a/core/crates/layerfs-persistence/src/backend/sqlite/unit_io.rs b/engine/crates/layerfs-persistence/src/backend/sqlite/unit_io.rs similarity index 100% rename from core/crates/layerfs-persistence/src/backend/sqlite/unit_io.rs rename to engine/crates/layerfs-persistence/src/backend/sqlite/unit_io.rs diff --git a/core/crates/layerfs-persistence/src/backend/sqlite/unit_layout.rs b/engine/crates/layerfs-persistence/src/backend/sqlite/unit_layout.rs similarity index 100% rename from core/crates/layerfs-persistence/src/backend/sqlite/unit_layout.rs rename to engine/crates/layerfs-persistence/src/backend/sqlite/unit_layout.rs diff --git a/core/crates/layerfs-persistence/src/backend/sqlite/units_publish.rs b/engine/crates/layerfs-persistence/src/backend/sqlite/units_publish.rs similarity index 100% rename from core/crates/layerfs-persistence/src/backend/sqlite/units_publish.rs rename to engine/crates/layerfs-persistence/src/backend/sqlite/units_publish.rs diff --git a/core/crates/layerfs-persistence/src/backend/sqlite/units_read.rs b/engine/crates/layerfs-persistence/src/backend/sqlite/units_read.rs similarity index 100% rename from core/crates/layerfs-persistence/src/backend/sqlite/units_read.rs rename to engine/crates/layerfs-persistence/src/backend/sqlite/units_read.rs diff --git a/core/crates/layerfs-persistence/src/backend/sqlite/writer_admission.rs b/engine/crates/layerfs-persistence/src/backend/sqlite/writer_admission.rs similarity index 100% rename from core/crates/layerfs-persistence/src/backend/sqlite/writer_admission.rs rename to engine/crates/layerfs-persistence/src/backend/sqlite/writer_admission.rs diff --git a/core/crates/layerfs-persistence/src/history/allocation.rs b/engine/crates/layerfs-persistence/src/history/allocation.rs similarity index 100% rename from core/crates/layerfs-persistence/src/history/allocation.rs rename to engine/crates/layerfs-persistence/src/history/allocation.rs diff --git a/core/crates/layerfs-persistence/src/history/ancestry.rs b/engine/crates/layerfs-persistence/src/history/ancestry.rs similarity index 100% rename from core/crates/layerfs-persistence/src/history/ancestry.rs rename to engine/crates/layerfs-persistence/src/history/ancestry.rs diff --git a/core/crates/layerfs-persistence/src/history/bindings.rs b/engine/crates/layerfs-persistence/src/history/bindings.rs similarity index 100% rename from core/crates/layerfs-persistence/src/history/bindings.rs rename to engine/crates/layerfs-persistence/src/history/bindings.rs diff --git a/core/crates/layerfs-persistence/src/history/branch.rs b/engine/crates/layerfs-persistence/src/history/branch.rs similarity index 100% rename from core/crates/layerfs-persistence/src/history/branch.rs rename to engine/crates/layerfs-persistence/src/history/branch.rs diff --git a/core/crates/layerfs-persistence/src/history/catalog.rs b/engine/crates/layerfs-persistence/src/history/catalog.rs similarity index 100% rename from core/crates/layerfs-persistence/src/history/catalog.rs rename to engine/crates/layerfs-persistence/src/history/catalog.rs diff --git a/core/crates/layerfs-persistence/src/history/commit.rs b/engine/crates/layerfs-persistence/src/history/commit.rs similarity index 100% rename from core/crates/layerfs-persistence/src/history/commit.rs rename to engine/crates/layerfs-persistence/src/history/commit.rs diff --git a/core/crates/layerfs-persistence/src/history/digests.rs b/engine/crates/layerfs-persistence/src/history/digests.rs similarity index 100% rename from core/crates/layerfs-persistence/src/history/digests.rs rename to engine/crates/layerfs-persistence/src/history/digests.rs diff --git a/core/crates/layerfs-persistence/src/history/facts.rs b/engine/crates/layerfs-persistence/src/history/facts.rs similarity index 100% rename from core/crates/layerfs-persistence/src/history/facts.rs rename to engine/crates/layerfs-persistence/src/history/facts.rs diff --git a/core/crates/layerfs-persistence/src/history/hints.rs b/engine/crates/layerfs-persistence/src/history/hints.rs similarity index 100% rename from core/crates/layerfs-persistence/src/history/hints.rs rename to engine/crates/layerfs-persistence/src/history/hints.rs diff --git a/core/crates/layerfs-persistence/src/history/layerstack.rs b/engine/crates/layerfs-persistence/src/history/layerstack.rs similarity index 100% rename from core/crates/layerfs-persistence/src/history/layerstack.rs rename to engine/crates/layerfs-persistence/src/history/layerstack.rs diff --git a/core/crates/layerfs-persistence/src/history/lineage.rs b/engine/crates/layerfs-persistence/src/history/lineage.rs similarity index 100% rename from core/crates/layerfs-persistence/src/history/lineage.rs rename to engine/crates/layerfs-persistence/src/history/lineage.rs diff --git a/core/crates/layerfs-persistence/src/history/lineage_backfill.rs b/engine/crates/layerfs-persistence/src/history/lineage_backfill.rs similarity index 100% rename from core/crates/layerfs-persistence/src/history/lineage_backfill.rs rename to engine/crates/layerfs-persistence/src/history/lineage_backfill.rs diff --git a/core/crates/layerfs-persistence/src/history/merge.rs b/engine/crates/layerfs-persistence/src/history/merge.rs similarity index 100% rename from core/crates/layerfs-persistence/src/history/merge.rs rename to engine/crates/layerfs-persistence/src/history/merge.rs diff --git a/core/crates/layerfs-persistence/src/history/mod.rs b/engine/crates/layerfs-persistence/src/history/mod.rs similarity index 100% rename from core/crates/layerfs-persistence/src/history/mod.rs rename to engine/crates/layerfs-persistence/src/history/mod.rs diff --git a/core/crates/layerfs-persistence/src/history/provider.rs b/engine/crates/layerfs-persistence/src/history/provider.rs similarity index 100% rename from core/crates/layerfs-persistence/src/history/provider.rs rename to engine/crates/layerfs-persistence/src/history/provider.rs diff --git a/core/crates/layerfs-persistence/src/history/rows.rs b/engine/crates/layerfs-persistence/src/history/rows.rs similarity index 100% rename from core/crates/layerfs-persistence/src/history/rows.rs rename to engine/crates/layerfs-persistence/src/history/rows.rs diff --git a/core/crates/layerfs-persistence/src/history/transaction.rs b/engine/crates/layerfs-persistence/src/history/transaction.rs similarity index 100% rename from core/crates/layerfs-persistence/src/history/transaction.rs rename to engine/crates/layerfs-persistence/src/history/transaction.rs diff --git a/core/crates/layerfs-persistence/src/lib.rs b/engine/crates/layerfs-persistence/src/lib.rs similarity index 100% rename from core/crates/layerfs-persistence/src/lib.rs rename to engine/crates/layerfs-persistence/src/lib.rs diff --git a/core/crates/layerfs-persistence/src/metadata/allocation.rs b/engine/crates/layerfs-persistence/src/metadata/allocation.rs similarity index 100% rename from core/crates/layerfs-persistence/src/metadata/allocation.rs rename to engine/crates/layerfs-persistence/src/metadata/allocation.rs diff --git a/core/crates/layerfs-persistence/src/metadata/locations.rs b/engine/crates/layerfs-persistence/src/metadata/locations.rs similarity index 100% rename from core/crates/layerfs-persistence/src/metadata/locations.rs rename to engine/crates/layerfs-persistence/src/metadata/locations.rs diff --git a/core/crates/layerfs-persistence/src/metadata/mod.rs b/engine/crates/layerfs-persistence/src/metadata/mod.rs similarity index 100% rename from core/crates/layerfs-persistence/src/metadata/mod.rs rename to engine/crates/layerfs-persistence/src/metadata/mod.rs diff --git a/core/crates/layerfs-persistence/src/metadata/policy.rs b/engine/crates/layerfs-persistence/src/metadata/policy.rs similarity index 100% rename from core/crates/layerfs-persistence/src/metadata/policy.rs rename to engine/crates/layerfs-persistence/src/metadata/policy.rs diff --git a/core/crates/layerfs-persistence/src/metadata/signatures.rs b/engine/crates/layerfs-persistence/src/metadata/signatures.rs similarity index 100% rename from core/crates/layerfs-persistence/src/metadata/signatures.rs rename to engine/crates/layerfs-persistence/src/metadata/signatures.rs diff --git a/core/crates/layerfs-persistence/src/metadata/values.rs b/engine/crates/layerfs-persistence/src/metadata/values.rs similarity index 100% rename from core/crates/layerfs-persistence/src/metadata/values.rs rename to engine/crates/layerfs-persistence/src/metadata/values.rs diff --git a/core/crates/layerfs-persistence/src/objects/mod.rs b/engine/crates/layerfs-persistence/src/objects/mod.rs similarity index 100% rename from core/crates/layerfs-persistence/src/objects/mod.rs rename to engine/crates/layerfs-persistence/src/objects/mod.rs diff --git a/core/crates/layerfs-persistence/src/objects/read.rs b/engine/crates/layerfs-persistence/src/objects/read.rs similarity index 100% rename from core/crates/layerfs-persistence/src/objects/read.rs rename to engine/crates/layerfs-persistence/src/objects/read.rs diff --git a/core/crates/layerfs-persistence/src/storage/acquisition/mod.rs b/engine/crates/layerfs-persistence/src/storage/acquisition/mod.rs similarity index 100% rename from core/crates/layerfs-persistence/src/storage/acquisition/mod.rs rename to engine/crates/layerfs-persistence/src/storage/acquisition/mod.rs diff --git a/core/crates/layerfs-persistence/src/storage/acquisition/provider.rs b/engine/crates/layerfs-persistence/src/storage/acquisition/provider.rs similarity index 100% rename from core/crates/layerfs-persistence/src/storage/acquisition/provider.rs rename to engine/crates/layerfs-persistence/src/storage/acquisition/provider.rs diff --git a/core/crates/layerfs-persistence/src/storage/merge_records.rs b/engine/crates/layerfs-persistence/src/storage/merge_records.rs similarity index 100% rename from core/crates/layerfs-persistence/src/storage/merge_records.rs rename to engine/crates/layerfs-persistence/src/storage/merge_records.rs diff --git a/core/crates/layerfs-persistence/src/storage/mod.rs b/engine/crates/layerfs-persistence/src/storage/mod.rs similarity index 100% rename from core/crates/layerfs-persistence/src/storage/mod.rs rename to engine/crates/layerfs-persistence/src/storage/mod.rs diff --git a/core/crates/layerfs-persistence/src/storage/provider.rs b/engine/crates/layerfs-persistence/src/storage/provider.rs similarity index 100% rename from core/crates/layerfs-persistence/src/storage/provider.rs rename to engine/crates/layerfs-persistence/src/storage/provider.rs diff --git a/core/crates/layerfs-persistence/src/storage/publication.rs b/engine/crates/layerfs-persistence/src/storage/publication.rs similarity index 100% rename from core/crates/layerfs-persistence/src/storage/publication.rs rename to engine/crates/layerfs-persistence/src/storage/publication.rs diff --git a/core/crates/layerfs-persistence/src/store/config.rs b/engine/crates/layerfs-persistence/src/store/config.rs similarity index 100% rename from core/crates/layerfs-persistence/src/store/config.rs rename to engine/crates/layerfs-persistence/src/store/config.rs diff --git a/core/crates/layerfs-persistence/src/store/handles.rs b/engine/crates/layerfs-persistence/src/store/handles.rs similarity index 100% rename from core/crates/layerfs-persistence/src/store/handles.rs rename to engine/crates/layerfs-persistence/src/store/handles.rs diff --git a/core/crates/layerfs-persistence/src/store/mod.rs b/engine/crates/layerfs-persistence/src/store/mod.rs similarity index 100% rename from core/crates/layerfs-persistence/src/store/mod.rs rename to engine/crates/layerfs-persistence/src/store/mod.rs diff --git a/core/crates/layerfs-persistence/src/store/open.rs b/engine/crates/layerfs-persistence/src/store/open.rs similarity index 100% rename from core/crates/layerfs-persistence/src/store/open.rs rename to engine/crates/layerfs-persistence/src/store/open.rs diff --git a/core/crates/layerfs-persistence/src/store/seal.rs b/engine/crates/layerfs-persistence/src/store/seal.rs similarity index 100% rename from core/crates/layerfs-persistence/src/store/seal.rs rename to engine/crates/layerfs-persistence/src/store/seal.rs diff --git a/core/crates/layerfs-persistence/tests/acquisition_batching.rs b/engine/crates/layerfs-persistence/tests/acquisition_batching.rs similarity index 100% rename from core/crates/layerfs-persistence/tests/acquisition_batching.rs rename to engine/crates/layerfs-persistence/tests/acquisition_batching.rs diff --git a/core/crates/layerfs-persistence/tests/acquisition_disposal.rs b/engine/crates/layerfs-persistence/tests/acquisition_disposal.rs similarity index 100% rename from core/crates/layerfs-persistence/tests/acquisition_disposal.rs rename to engine/crates/layerfs-persistence/tests/acquisition_disposal.rs diff --git a/core/crates/layerfs-persistence/tests/acquisition_reads.rs b/engine/crates/layerfs-persistence/tests/acquisition_reads.rs similarity index 100% rename from core/crates/layerfs-persistence/tests/acquisition_reads.rs rename to engine/crates/layerfs-persistence/tests/acquisition_reads.rs diff --git a/core/crates/layerfs-persistence/tests/concurrent_first_installs.rs b/engine/crates/layerfs-persistence/tests/concurrent_first_installs.rs similarity index 100% rename from core/crates/layerfs-persistence/tests/concurrent_first_installs.rs rename to engine/crates/layerfs-persistence/tests/concurrent_first_installs.rs diff --git a/core/crates/layerfs-persistence/tests/concurrent_pooled_saves.rs b/engine/crates/layerfs-persistence/tests/concurrent_pooled_saves.rs similarity index 100% rename from core/crates/layerfs-persistence/tests/concurrent_pooled_saves.rs rename to engine/crates/layerfs-persistence/tests/concurrent_pooled_saves.rs diff --git a/core/crates/layerfs-persistence/tests/diagnostics_during_lane.rs b/engine/crates/layerfs-persistence/tests/diagnostics_during_lane.rs similarity index 100% rename from core/crates/layerfs-persistence/tests/diagnostics_during_lane.rs rename to engine/crates/layerfs-persistence/tests/diagnostics_during_lane.rs diff --git a/core/crates/layerfs-persistence/tests/disposable_startup_sync.rs b/engine/crates/layerfs-persistence/tests/disposable_startup_sync.rs similarity index 100% rename from core/crates/layerfs-persistence/tests/disposable_startup_sync.rs rename to engine/crates/layerfs-persistence/tests/disposable_startup_sync.rs diff --git a/core/crates/layerfs-persistence/tests/file_lengths.rs b/engine/crates/layerfs-persistence/tests/file_lengths.rs similarity index 100% rename from core/crates/layerfs-persistence/tests/file_lengths.rs rename to engine/crates/layerfs-persistence/tests/file_lengths.rs diff --git a/core/crates/layerfs-persistence/tests/history_allocation.rs b/engine/crates/layerfs-persistence/tests/history_allocation.rs similarity index 100% rename from core/crates/layerfs-persistence/tests/history_allocation.rs rename to engine/crates/layerfs-persistence/tests/history_allocation.rs diff --git a/core/crates/layerfs-persistence/tests/history_remediation.rs b/engine/crates/layerfs-persistence/tests/history_remediation.rs similarity index 100% rename from core/crates/layerfs-persistence/tests/history_remediation.rs rename to engine/crates/layerfs-persistence/tests/history_remediation.rs diff --git a/core/crates/layerfs-persistence/tests/immutable_reads_under_reclamation.rs b/engine/crates/layerfs-persistence/tests/immutable_reads_under_reclamation.rs similarity index 100% rename from core/crates/layerfs-persistence/tests/immutable_reads_under_reclamation.rs rename to engine/crates/layerfs-persistence/tests/immutable_reads_under_reclamation.rs diff --git a/core/crates/layerfs-persistence/tests/inode_branch_delta_custody.rs b/engine/crates/layerfs-persistence/tests/inode_branch_delta_custody.rs similarity index 100% rename from core/crates/layerfs-persistence/tests/inode_branch_delta_custody.rs rename to engine/crates/layerfs-persistence/tests/inode_branch_delta_custody.rs diff --git a/core/crates/layerfs-persistence/tests/interleaved_saves.rs b/engine/crates/layerfs-persistence/tests/interleaved_saves.rs similarity index 100% rename from core/crates/layerfs-persistence/tests/interleaved_saves.rs rename to engine/crates/layerfs-persistence/tests/interleaved_saves.rs diff --git a/core/crates/layerfs-persistence/tests/lineage_backfill.rs b/engine/crates/layerfs-persistence/tests/lineage_backfill.rs similarity index 100% rename from core/crates/layerfs-persistence/tests/lineage_backfill.rs rename to engine/crates/layerfs-persistence/tests/lineage_backfill.rs diff --git a/core/crates/layerfs-persistence/tests/lineage_backfill_measure.rs b/engine/crates/layerfs-persistence/tests/lineage_backfill_measure.rs similarity index 100% rename from core/crates/layerfs-persistence/tests/lineage_backfill_measure.rs rename to engine/crates/layerfs-persistence/tests/lineage_backfill_measure.rs diff --git a/core/crates/layerfs-persistence/tests/merge_records.rs b/engine/crates/layerfs-persistence/tests/merge_records.rs similarity index 100% rename from core/crates/layerfs-persistence/tests/merge_records.rs rename to engine/crates/layerfs-persistence/tests/merge_records.rs diff --git a/core/crates/layerfs-persistence/tests/old_format_open.rs b/engine/crates/layerfs-persistence/tests/old_format_open.rs similarity index 100% rename from core/crates/layerfs-persistence/tests/old_format_open.rs rename to engine/crates/layerfs-persistence/tests/old_format_open.rs diff --git a/core/crates/layerfs-persistence/tests/seal_allocation.rs b/engine/crates/layerfs-persistence/tests/seal_allocation.rs similarity index 100% rename from core/crates/layerfs-persistence/tests/seal_allocation.rs rename to engine/crates/layerfs-persistence/tests/seal_allocation.rs diff --git a/core/crates/layerfs-persistence/tests/semantic_admission.rs b/engine/crates/layerfs-persistence/tests/semantic_admission.rs similarity index 100% rename from core/crates/layerfs-persistence/tests/semantic_admission.rs rename to engine/crates/layerfs-persistence/tests/semantic_admission.rs diff --git a/core/crates/layerfs-persistence/tests/serverless_store.rs b/engine/crates/layerfs-persistence/tests/serverless_store.rs similarity index 100% rename from core/crates/layerfs-persistence/tests/serverless_store.rs rename to engine/crates/layerfs-persistence/tests/serverless_store.rs diff --git a/core/crates/layerfs-persistence/tests/signature_ring_order.rs b/engine/crates/layerfs-persistence/tests/signature_ring_order.rs similarity index 100% rename from core/crates/layerfs-persistence/tests/signature_ring_order.rs rename to engine/crates/layerfs-persistence/tests/signature_ring_order.rs diff --git a/core/crates/layerfs-persistence/tests/space_reclamation.rs b/engine/crates/layerfs-persistence/tests/space_reclamation.rs similarity index 100% rename from core/crates/layerfs-persistence/tests/space_reclamation.rs rename to engine/crates/layerfs-persistence/tests/space_reclamation.rs diff --git a/core/crates/layerfs-persistence/tests/sqlite_group_rows.rs b/engine/crates/layerfs-persistence/tests/sqlite_group_rows.rs similarity index 100% rename from core/crates/layerfs-persistence/tests/sqlite_group_rows.rs rename to engine/crates/layerfs-persistence/tests/sqlite_group_rows.rs diff --git a/core/crates/layerfs-persistence/tests/sqlite_group_rows_indexed.rs b/engine/crates/layerfs-persistence/tests/sqlite_group_rows_indexed.rs similarity index 100% rename from core/crates/layerfs-persistence/tests/sqlite_group_rows_indexed.rs rename to engine/crates/layerfs-persistence/tests/sqlite_group_rows_indexed.rs diff --git a/core/crates/layerfs-persistence/tests/sqlite_inode_values.rs b/engine/crates/layerfs-persistence/tests/sqlite_inode_values.rs similarity index 100% rename from core/crates/layerfs-persistence/tests/sqlite_inode_values.rs rename to engine/crates/layerfs-persistence/tests/sqlite_inode_values.rs diff --git a/core/crates/layerfs-persistence/tests/sqlite_lock_custody.rs b/engine/crates/layerfs-persistence/tests/sqlite_lock_custody.rs similarity index 100% rename from core/crates/layerfs-persistence/tests/sqlite_lock_custody.rs rename to engine/crates/layerfs-persistence/tests/sqlite_lock_custody.rs diff --git a/core/crates/layerfs-persistence/tests/sqlite_ordinal_lookahead.rs b/engine/crates/layerfs-persistence/tests/sqlite_ordinal_lookahead.rs similarity index 100% rename from core/crates/layerfs-persistence/tests/sqlite_ordinal_lookahead.rs rename to engine/crates/layerfs-persistence/tests/sqlite_ordinal_lookahead.rs diff --git a/core/crates/layerfs-persistence/tests/sqlite_pack_selection.rs b/engine/crates/layerfs-persistence/tests/sqlite_pack_selection.rs similarity index 100% rename from core/crates/layerfs-persistence/tests/sqlite_pack_selection.rs rename to engine/crates/layerfs-persistence/tests/sqlite_pack_selection.rs diff --git a/core/crates/layerfs-persistence/tests/sqlite_publication.rs b/engine/crates/layerfs-persistence/tests/sqlite_publication.rs similarity index 100% rename from core/crates/layerfs-persistence/tests/sqlite_publication.rs rename to engine/crates/layerfs-persistence/tests/sqlite_publication.rs diff --git a/core/crates/layerfs-persistence/tests/sqlite_recovery.rs b/engine/crates/layerfs-persistence/tests/sqlite_recovery.rs similarity index 100% rename from core/crates/layerfs-persistence/tests/sqlite_recovery.rs rename to engine/crates/layerfs-persistence/tests/sqlite_recovery.rs diff --git a/core/crates/layerfs-persistence/tests/sqlite_reference_acquisition.rs b/engine/crates/layerfs-persistence/tests/sqlite_reference_acquisition.rs similarity index 100% rename from core/crates/layerfs-persistence/tests/sqlite_reference_acquisition.rs rename to engine/crates/layerfs-persistence/tests/sqlite_reference_acquisition.rs diff --git a/core/crates/layerfs-persistence/tests/sqlite_transaction_units.rs b/engine/crates/layerfs-persistence/tests/sqlite_transaction_units.rs similarity index 100% rename from core/crates/layerfs-persistence/tests/sqlite_transaction_units.rs rename to engine/crates/layerfs-persistence/tests/sqlite_transaction_units.rs diff --git a/core/crates/layerfs-persistence/tests/support/mod.rs b/engine/crates/layerfs-persistence/tests/support/mod.rs similarity index 100% rename from core/crates/layerfs-persistence/tests/support/mod.rs rename to engine/crates/layerfs-persistence/tests/support/mod.rs diff --git a/core/crates/layerfs-persistence/tests/thread_work.rs b/engine/crates/layerfs-persistence/tests/thread_work.rs similarity index 100% rename from core/crates/layerfs-persistence/tests/thread_work.rs rename to engine/crates/layerfs-persistence/tests/thread_work.rs diff --git a/core/crates/layerfs-persistence/tests/writer_admission.rs b/engine/crates/layerfs-persistence/tests/writer_admission.rs similarity index 100% rename from core/crates/layerfs-persistence/tests/writer_admission.rs rename to engine/crates/layerfs-persistence/tests/writer_admission.rs diff --git a/core/crates/layerfs-project/Cargo.toml b/engine/crates/layerfs-project/Cargo.toml similarity index 55% rename from core/crates/layerfs-project/Cargo.toml rename to engine/crates/layerfs-project/Cargo.toml index 57f132685..b1311655b 100644 --- a/core/crates/layerfs-project/Cargo.toml +++ b/engine/crates/layerfs-project/Cargo.toml @@ -7,10 +7,10 @@ rust-version.workspace = true license.workspace = true [dependencies] -layerfs-content = { path = "../layerfs-content" } -layerfs-storage = { path = "../layerfs-storage" } -layerfs-history = { path = "../layerfs-history", default-features = false } -layerfs-telemetry = { path = "../layerfs-telemetry" } +layerfs-content = { path = "../../../core/crates/layerfs-content" } +layerfs-storage = { path = "../../../core/crates/layerfs-storage" } +layerfs-history = { path = "../../../core/crates/layerfs-history", default-features = false } +layerfs-telemetry = { path = "../../../core/crates/layerfs-telemetry" } layerfs-persistence = { path = "../layerfs-persistence" } layerfs-bridge = { path = "../layerfs-bridge" } diff --git a/core/crates/layerfs-project/examples/acquisition_profile.rs b/engine/crates/layerfs-project/examples/acquisition_profile.rs similarity index 100% rename from core/crates/layerfs-project/examples/acquisition_profile.rs rename to engine/crates/layerfs-project/examples/acquisition_profile.rs diff --git a/core/crates/layerfs-project/examples/benchmark_init.rs b/engine/crates/layerfs-project/examples/benchmark_init.rs similarity index 100% rename from core/crates/layerfs-project/examples/benchmark_init.rs rename to engine/crates/layerfs-project/examples/benchmark_init.rs diff --git a/core/crates/layerfs-project/examples/durable_init_costs.rs b/engine/crates/layerfs-project/examples/durable_init_costs.rs similarity index 100% rename from core/crates/layerfs-project/examples/durable_init_costs.rs rename to engine/crates/layerfs-project/examples/durable_init_costs.rs diff --git a/core/crates/layerfs-project/examples/durable_init_costs/vfs.rs b/engine/crates/layerfs-project/examples/durable_init_costs/vfs.rs similarity index 100% rename from core/crates/layerfs-project/examples/durable_init_costs/vfs.rs rename to engine/crates/layerfs-project/examples/durable_init_costs/vfs.rs diff --git a/core/crates/layerfs-project/examples/history_support/canonical_memo.rs b/engine/crates/layerfs-project/examples/history_support/canonical_memo.rs similarity index 100% rename from core/crates/layerfs-project/examples/history_support/canonical_memo.rs rename to engine/crates/layerfs-project/examples/history_support/canonical_memo.rs diff --git a/core/crates/layerfs-project/examples/verify_namespace.rs b/engine/crates/layerfs-project/examples/verify_namespace.rs similarity index 100% rename from core/crates/layerfs-project/examples/verify_namespace.rs rename to engine/crates/layerfs-project/examples/verify_namespace.rs diff --git a/core/crates/layerfs-project/src/import/backing.rs b/engine/crates/layerfs-project/src/import/backing.rs similarity index 100% rename from core/crates/layerfs-project/src/import/backing.rs rename to engine/crates/layerfs-project/src/import/backing.rs diff --git a/core/crates/layerfs-project/src/import/batch.rs b/engine/crates/layerfs-project/src/import/batch.rs similarity index 100% rename from core/crates/layerfs-project/src/import/batch.rs rename to engine/crates/layerfs-project/src/import/batch.rs diff --git a/core/crates/layerfs-project/src/import/error.rs b/engine/crates/layerfs-project/src/import/error.rs similarity index 100% rename from core/crates/layerfs-project/src/import/error.rs rename to engine/crates/layerfs-project/src/import/error.rs diff --git a/core/crates/layerfs-project/src/import/files.rs b/engine/crates/layerfs-project/src/import/files.rs similarity index 100% rename from core/crates/layerfs-project/src/import/files.rs rename to engine/crates/layerfs-project/src/import/files.rs diff --git a/core/crates/layerfs-project/src/import/hints.rs b/engine/crates/layerfs-project/src/import/hints.rs similarity index 100% rename from core/crates/layerfs-project/src/import/hints.rs rename to engine/crates/layerfs-project/src/import/hints.rs diff --git a/core/crates/layerfs-project/src/import/init.rs b/engine/crates/layerfs-project/src/import/init.rs similarity index 100% rename from core/crates/layerfs-project/src/import/init.rs rename to engine/crates/layerfs-project/src/import/init.rs diff --git a/core/crates/layerfs-project/src/import/mod.rs b/engine/crates/layerfs-project/src/import/mod.rs similarity index 100% rename from core/crates/layerfs-project/src/import/mod.rs rename to engine/crates/layerfs-project/src/import/mod.rs diff --git a/core/crates/layerfs-project/src/import/namespace.rs b/engine/crates/layerfs-project/src/import/namespace.rs similarity index 100% rename from core/crates/layerfs-project/src/import/namespace.rs rename to engine/crates/layerfs-project/src/import/namespace.rs diff --git a/core/crates/layerfs-project/src/import/observe.rs b/engine/crates/layerfs-project/src/import/observe.rs similarity index 100% rename from core/crates/layerfs-project/src/import/observe.rs rename to engine/crates/layerfs-project/src/import/observe.rs diff --git a/core/crates/layerfs-project/src/import/scan.rs b/engine/crates/layerfs-project/src/import/scan.rs similarity index 100% rename from core/crates/layerfs-project/src/import/scan.rs rename to engine/crates/layerfs-project/src/import/scan.rs diff --git a/core/crates/layerfs-project/src/import/source.rs b/engine/crates/layerfs-project/src/import/source.rs similarity index 100% rename from core/crates/layerfs-project/src/import/source.rs rename to engine/crates/layerfs-project/src/import/source.rs diff --git a/core/crates/layerfs-project/src/import/work.rs b/engine/crates/layerfs-project/src/import/work.rs similarity index 100% rename from core/crates/layerfs-project/src/import/work.rs rename to engine/crates/layerfs-project/src/import/work.rs diff --git a/core/crates/layerfs-project/src/lib.rs b/engine/crates/layerfs-project/src/lib.rs similarity index 100% rename from core/crates/layerfs-project/src/lib.rs rename to engine/crates/layerfs-project/src/lib.rs diff --git a/core/crates/layerfs-project/src/store/init.rs b/engine/crates/layerfs-project/src/store/init.rs similarity index 100% rename from core/crates/layerfs-project/src/store/init.rs rename to engine/crates/layerfs-project/src/store/init.rs diff --git a/core/crates/layerfs-project/src/store/install.rs b/engine/crates/layerfs-project/src/store/install.rs similarity index 100% rename from core/crates/layerfs-project/src/store/install.rs rename to engine/crates/layerfs-project/src/store/install.rs diff --git a/core/crates/layerfs-project/src/store/install_types.rs b/engine/crates/layerfs-project/src/store/install_types.rs similarity index 100% rename from core/crates/layerfs-project/src/store/install_types.rs rename to engine/crates/layerfs-project/src/store/install_types.rs diff --git a/core/crates/layerfs-project/src/store/mod.rs b/engine/crates/layerfs-project/src/store/mod.rs similarity index 100% rename from core/crates/layerfs-project/src/store/mod.rs rename to engine/crates/layerfs-project/src/store/mod.rs diff --git a/core/crates/layerfs-project/tests/acquisition_custody.rs b/engine/crates/layerfs-project/tests/acquisition_custody.rs similarity index 100% rename from core/crates/layerfs-project/tests/acquisition_custody.rs rename to engine/crates/layerfs-project/tests/acquisition_custody.rs diff --git a/core/crates/layerfs-project/tests/backed_acquisition.rs b/engine/crates/layerfs-project/tests/backed_acquisition.rs similarity index 100% rename from core/crates/layerfs-project/tests/backed_acquisition.rs rename to engine/crates/layerfs-project/tests/backed_acquisition.rs diff --git a/core/crates/layerfs-project/tests/complete_root.rs b/engine/crates/layerfs-project/tests/complete_root.rs similarity index 100% rename from core/crates/layerfs-project/tests/complete_root.rs rename to engine/crates/layerfs-project/tests/complete_root.rs diff --git a/core/crates/layerfs-project/tests/history_proof_memo.rs b/engine/crates/layerfs-project/tests/history_proof_memo.rs similarity index 100% rename from core/crates/layerfs-project/tests/history_proof_memo.rs rename to engine/crates/layerfs-project/tests/history_proof_memo.rs diff --git a/core/crates/layerfs-project/tests/init_counters.rs b/engine/crates/layerfs-project/tests/init_counters.rs similarity index 100% rename from core/crates/layerfs-project/tests/init_counters.rs rename to engine/crates/layerfs-project/tests/init_counters.rs diff --git a/core/crates/layerfs-project/tests/init_memory.rs b/engine/crates/layerfs-project/tests/init_memory.rs similarity index 100% rename from core/crates/layerfs-project/tests/init_memory.rs rename to engine/crates/layerfs-project/tests/init_memory.rs diff --git a/core/crates/layerfs-project/tests/init_sqlite.rs b/engine/crates/layerfs-project/tests/init_sqlite.rs similarity index 100% rename from core/crates/layerfs-project/tests/init_sqlite.rs rename to engine/crates/layerfs-project/tests/init_sqlite.rs diff --git a/core/crates/layerfs-project/tests/namespace_scaling.rs b/engine/crates/layerfs-project/tests/namespace_scaling.rs similarity index 100% rename from core/crates/layerfs-project/tests/namespace_scaling.rs rename to engine/crates/layerfs-project/tests/namespace_scaling.rs diff --git a/core/crates/layerfs-project/tests/support/memory_acquisition.rs b/engine/crates/layerfs-project/tests/support/memory_acquisition.rs similarity index 100% rename from core/crates/layerfs-project/tests/support/memory_acquisition.rs rename to engine/crates/layerfs-project/tests/support/memory_acquisition.rs diff --git a/core/crates/layerfs-project/tests/support/memory_history.rs b/engine/crates/layerfs-project/tests/support/memory_history.rs similarity index 100% rename from core/crates/layerfs-project/tests/support/memory_history.rs rename to engine/crates/layerfs-project/tests/support/memory_history.rs diff --git a/core/crates/layerfs-project/tests/support/memory_objects.rs b/engine/crates/layerfs-project/tests/support/memory_objects.rs similarity index 100% rename from core/crates/layerfs-project/tests/support/memory_objects.rs rename to engine/crates/layerfs-project/tests/support/memory_objects.rs diff --git a/core/crates/layerfs-project/tests/support/mod.rs b/engine/crates/layerfs-project/tests/support/mod.rs similarity index 98% rename from core/crates/layerfs-project/tests/support/mod.rs rename to engine/crates/layerfs-project/tests/support/mod.rs index 7f517336e..94caa4bec 100644 --- a/core/crates/layerfs-project/tests/support/mod.rs +++ b/engine/crates/layerfs-project/tests/support/mod.rs @@ -23,7 +23,7 @@ use std::{ }; pub mod memory_acquisition; pub mod memory_history; -#[path = "../../../layerfs-storage/tests/support/memory_metadata.rs"] +#[path = "../../../../../core/crates/layerfs-storage/tests/support/memory_metadata.rs"] pub mod memory_metadata; pub struct Fixture { pub path: PathBuf, diff --git a/core/crates/layerfs-project/tests/support/old_snapshot.rs b/engine/crates/layerfs-project/tests/support/old_snapshot.rs similarity index 100% rename from core/crates/layerfs-project/tests/support/old_snapshot.rs rename to engine/crates/layerfs-project/tests/support/old_snapshot.rs diff --git a/core/crates/layerfs-sandbox/Cargo.toml b/engine/crates/layerfs-sandbox/Cargo.toml similarity index 100% rename from core/crates/layerfs-sandbox/Cargo.toml rename to engine/crates/layerfs-sandbox/Cargo.toml diff --git a/core/crates/layerfs-sandbox/examples/engine_streams.rs b/engine/crates/layerfs-sandbox/examples/engine_streams.rs similarity index 100% rename from core/crates/layerfs-sandbox/examples/engine_streams.rs rename to engine/crates/layerfs-sandbox/examples/engine_streams.rs diff --git a/core/crates/layerfs-sandbox/src/backend/docker/archive.rs b/engine/crates/layerfs-sandbox/src/backend/docker/archive.rs similarity index 100% rename from core/crates/layerfs-sandbox/src/backend/docker/archive.rs rename to engine/crates/layerfs-sandbox/src/backend/docker/archive.rs diff --git a/core/crates/layerfs-sandbox/src/backend/docker/body.rs b/engine/crates/layerfs-sandbox/src/backend/docker/body.rs similarity index 100% rename from core/crates/layerfs-sandbox/src/backend/docker/body.rs rename to engine/crates/layerfs-sandbox/src/backend/docker/body.rs diff --git a/core/crates/layerfs-sandbox/src/backend/docker/container.rs b/engine/crates/layerfs-sandbox/src/backend/docker/container.rs similarity index 100% rename from core/crates/layerfs-sandbox/src/backend/docker/container.rs rename to engine/crates/layerfs-sandbox/src/backend/docker/container.rs diff --git a/core/crates/layerfs-sandbox/src/backend/docker/container_types.rs b/engine/crates/layerfs-sandbox/src/backend/docker/container_types.rs similarity index 100% rename from core/crates/layerfs-sandbox/src/backend/docker/container_types.rs rename to engine/crates/layerfs-sandbox/src/backend/docker/container_types.rs diff --git a/core/crates/layerfs-sandbox/src/backend/docker/endpoint.rs b/engine/crates/layerfs-sandbox/src/backend/docker/endpoint.rs similarity index 100% rename from core/crates/layerfs-sandbox/src/backend/docker/endpoint.rs rename to engine/crates/layerfs-sandbox/src/backend/docker/endpoint.rs diff --git a/core/crates/layerfs-sandbox/src/backend/docker/headers.rs b/engine/crates/layerfs-sandbox/src/backend/docker/headers.rs similarity index 100% rename from core/crates/layerfs-sandbox/src/backend/docker/headers.rs rename to engine/crates/layerfs-sandbox/src/backend/docker/headers.rs diff --git a/core/crates/layerfs-sandbox/src/backend/docker/http.rs b/engine/crates/layerfs-sandbox/src/backend/docker/http.rs similarity index 100% rename from core/crates/layerfs-sandbox/src/backend/docker/http.rs rename to engine/crates/layerfs-sandbox/src/backend/docker/http.rs diff --git a/core/crates/layerfs-sandbox/src/backend/docker/inspect.rs b/engine/crates/layerfs-sandbox/src/backend/docker/inspect.rs similarity index 100% rename from core/crates/layerfs-sandbox/src/backend/docker/inspect.rs rename to engine/crates/layerfs-sandbox/src/backend/docker/inspect.rs diff --git a/core/crates/layerfs-sandbox/src/backend/docker/json.rs b/engine/crates/layerfs-sandbox/src/backend/docker/json.rs similarity index 100% rename from core/crates/layerfs-sandbox/src/backend/docker/json.rs rename to engine/crates/layerfs-sandbox/src/backend/docker/json.rs diff --git a/core/crates/layerfs-sandbox/src/backend/docker/listener.rs b/engine/crates/layerfs-sandbox/src/backend/docker/listener.rs similarity index 100% rename from core/crates/layerfs-sandbox/src/backend/docker/listener.rs rename to engine/crates/layerfs-sandbox/src/backend/docker/listener.rs diff --git a/core/crates/layerfs-sandbox/src/backend/docker/mod.rs b/engine/crates/layerfs-sandbox/src/backend/docker/mod.rs similarity index 100% rename from core/crates/layerfs-sandbox/src/backend/docker/mod.rs rename to engine/crates/layerfs-sandbox/src/backend/docker/mod.rs diff --git a/core/crates/layerfs-sandbox/src/backend/docker/mux.rs b/engine/crates/layerfs-sandbox/src/backend/docker/mux.rs similarity index 100% rename from core/crates/layerfs-sandbox/src/backend/docker/mux.rs rename to engine/crates/layerfs-sandbox/src/backend/docker/mux.rs diff --git a/core/crates/layerfs-sandbox/src/backend/docker/request.rs b/engine/crates/layerfs-sandbox/src/backend/docker/request.rs similarity index 100% rename from core/crates/layerfs-sandbox/src/backend/docker/request.rs rename to engine/crates/layerfs-sandbox/src/backend/docker/request.rs diff --git a/core/crates/layerfs-sandbox/src/backend/docker/socket.rs b/engine/crates/layerfs-sandbox/src/backend/docker/socket.rs similarity index 100% rename from core/crates/layerfs-sandbox/src/backend/docker/socket.rs rename to engine/crates/layerfs-sandbox/src/backend/docker/socket.rs diff --git a/core/crates/layerfs-sandbox/src/backend/docker/streams.rs b/engine/crates/layerfs-sandbox/src/backend/docker/streams.rs similarity index 100% rename from core/crates/layerfs-sandbox/src/backend/docker/streams.rs rename to engine/crates/layerfs-sandbox/src/backend/docker/streams.rs diff --git a/core/crates/layerfs-sandbox/src/backend/docker/strings.rs b/engine/crates/layerfs-sandbox/src/backend/docker/strings.rs similarity index 100% rename from core/crates/layerfs-sandbox/src/backend/docker/strings.rs rename to engine/crates/layerfs-sandbox/src/backend/docker/strings.rs diff --git a/core/crates/layerfs-sandbox/src/backend/docker/topology.rs b/engine/crates/layerfs-sandbox/src/backend/docker/topology.rs similarity index 100% rename from core/crates/layerfs-sandbox/src/backend/docker/topology.rs rename to engine/crates/layerfs-sandbox/src/backend/docker/topology.rs diff --git a/core/crates/layerfs-sandbox/src/backend/mod.rs b/engine/crates/layerfs-sandbox/src/backend/mod.rs similarity index 100% rename from core/crates/layerfs-sandbox/src/backend/mod.rs rename to engine/crates/layerfs-sandbox/src/backend/mod.rs diff --git a/core/crates/layerfs-sandbox/src/lib.rs b/engine/crates/layerfs-sandbox/src/lib.rs similarity index 100% rename from core/crates/layerfs-sandbox/src/lib.rs rename to engine/crates/layerfs-sandbox/src/lib.rs diff --git a/core/crates/layerfs-sandbox/src/types/execution.rs b/engine/crates/layerfs-sandbox/src/types/execution.rs similarity index 100% rename from core/crates/layerfs-sandbox/src/types/execution.rs rename to engine/crates/layerfs-sandbox/src/types/execution.rs diff --git a/core/crates/layerfs-sandbox/src/types/failure.rs b/engine/crates/layerfs-sandbox/src/types/failure.rs similarity index 100% rename from core/crates/layerfs-sandbox/src/types/failure.rs rename to engine/crates/layerfs-sandbox/src/types/failure.rs diff --git a/core/crates/layerfs-sandbox/src/types/identity.rs b/engine/crates/layerfs-sandbox/src/types/identity.rs similarity index 100% rename from core/crates/layerfs-sandbox/src/types/identity.rs rename to engine/crates/layerfs-sandbox/src/types/identity.rs diff --git a/core/crates/layerfs-sandbox/src/types/mod.rs b/engine/crates/layerfs-sandbox/src/types/mod.rs similarity index 100% rename from core/crates/layerfs-sandbox/src/types/mod.rs rename to engine/crates/layerfs-sandbox/src/types/mod.rs diff --git a/core/crates/layerfs-sandbox/src/types/transfer.rs b/engine/crates/layerfs-sandbox/src/types/transfer.rs similarity index 100% rename from core/crates/layerfs-sandbox/src/types/transfer.rs rename to engine/crates/layerfs-sandbox/src/types/transfer.rs diff --git a/core/crates/layerfs-sandbox/tests/container_labels.rs b/engine/crates/layerfs-sandbox/tests/container_labels.rs similarity index 100% rename from core/crates/layerfs-sandbox/tests/container_labels.rs rename to engine/crates/layerfs-sandbox/tests/container_labels.rs diff --git a/core/crates/layerfs-sandbox/tests/docker_naming.rs b/engine/crates/layerfs-sandbox/tests/docker_naming.rs similarity index 100% rename from core/crates/layerfs-sandbox/tests/docker_naming.rs rename to engine/crates/layerfs-sandbox/tests/docker_naming.rs diff --git a/core/crates/layerfs-sandbox/tests/engine_keepalive.rs b/engine/crates/layerfs-sandbox/tests/engine_keepalive.rs similarity index 100% rename from core/crates/layerfs-sandbox/tests/engine_keepalive.rs rename to engine/crates/layerfs-sandbox/tests/engine_keepalive.rs diff --git a/core/crates/layerfs-sandbox/tests/engine_lifecycle.rs b/engine/crates/layerfs-sandbox/tests/engine_lifecycle.rs similarity index 100% rename from core/crates/layerfs-sandbox/tests/engine_lifecycle.rs rename to engine/crates/layerfs-sandbox/tests/engine_lifecycle.rs diff --git a/core/crates/layerfs-sandbox/tests/engine_protocol.rs b/engine/crates/layerfs-sandbox/tests/engine_protocol.rs similarity index 100% rename from core/crates/layerfs-sandbox/tests/engine_protocol.rs rename to engine/crates/layerfs-sandbox/tests/engine_protocol.rs diff --git a/core/crates/layerfs-sandbox/tests/support/engine.rs b/engine/crates/layerfs-sandbox/tests/support/engine.rs similarity index 100% rename from core/crates/layerfs-sandbox/tests/support/engine.rs rename to engine/crates/layerfs-sandbox/tests/support/engine.rs diff --git a/core/crates/layerfs-store-service/Cargo.toml b/engine/crates/layerfs-store-service/Cargo.toml similarity index 72% rename from core/crates/layerfs-store-service/Cargo.toml rename to engine/crates/layerfs-store-service/Cargo.toml index cb9fe0d57..058682143 100644 --- a/core/crates/layerfs-store-service/Cargo.toml +++ b/engine/crates/layerfs-store-service/Cargo.toml @@ -10,10 +10,10 @@ license.workspace = true layerfs-overlay = { path = "../layerfs-overlay" } layerfs-workspace = { path = "../layerfs-workspace" } layerfs-bridge = { path = "../layerfs-bridge" } -layerfs-content = { path = "../layerfs-content" } -layerfs-storage = { path = "../layerfs-storage" } -layerfs-history = { path = "../layerfs-history" } -layerfs-telemetry = { path = "../layerfs-telemetry" } +layerfs-content = { path = "../../../core/crates/layerfs-content" } +layerfs-storage = { path = "../../../core/crates/layerfs-storage" } +layerfs-history = { path = "../../../core/crates/layerfs-history" } +layerfs-telemetry = { path = "../../../core/crates/layerfs-telemetry" } # Concrete Store opening (bootstrap) and the kernel guard's open. layerfs-persistence = { path = "../layerfs-persistence" } nix = { version = "=0.31.3", default-features = false, features = ["fs"] } diff --git a/core/crates/layerfs-store-service/src/bootstrap.rs b/engine/crates/layerfs-store-service/src/bootstrap.rs similarity index 100% rename from core/crates/layerfs-store-service/src/bootstrap.rs rename to engine/crates/layerfs-store-service/src/bootstrap.rs diff --git a/core/crates/layerfs-store-service/src/history/branch.rs b/engine/crates/layerfs-store-service/src/history/branch.rs similarity index 100% rename from core/crates/layerfs-store-service/src/history/branch.rs rename to engine/crates/layerfs-store-service/src/history/branch.rs diff --git a/core/crates/layerfs-store-service/src/history/lookup.rs b/engine/crates/layerfs-store-service/src/history/lookup.rs similarity index 100% rename from core/crates/layerfs-store-service/src/history/lookup.rs rename to engine/crates/layerfs-store-service/src/history/lookup.rs diff --git a/core/crates/layerfs-store-service/src/history/mod.rs b/engine/crates/layerfs-store-service/src/history/mod.rs similarity index 100% rename from core/crates/layerfs-store-service/src/history/mod.rs rename to engine/crates/layerfs-store-service/src/history/mod.rs diff --git a/core/crates/layerfs-store-service/src/history/units.rs b/engine/crates/layerfs-store-service/src/history/units.rs similarity index 100% rename from core/crates/layerfs-store-service/src/history/units.rs rename to engine/crates/layerfs-store-service/src/history/units.rs diff --git a/core/crates/layerfs-store-service/src/install.rs b/engine/crates/layerfs-store-service/src/install.rs similarity index 100% rename from core/crates/layerfs-store-service/src/install.rs rename to engine/crates/layerfs-store-service/src/install.rs diff --git a/core/crates/layerfs-store-service/src/kernel_guard.rs b/engine/crates/layerfs-store-service/src/kernel_guard.rs similarity index 100% rename from core/crates/layerfs-store-service/src/kernel_guard.rs rename to engine/crates/layerfs-store-service/src/kernel_guard.rs diff --git a/core/crates/layerfs-store-service/src/lib.rs b/engine/crates/layerfs-store-service/src/lib.rs similarity index 100% rename from core/crates/layerfs-store-service/src/lib.rs rename to engine/crates/layerfs-store-service/src/lib.rs diff --git a/core/crates/layerfs-store-service/src/operator/args.rs b/engine/crates/layerfs-store-service/src/operator/args.rs similarity index 100% rename from core/crates/layerfs-store-service/src/operator/args.rs rename to engine/crates/layerfs-store-service/src/operator/args.rs diff --git a/core/crates/layerfs-store-service/src/operator/dispatch.rs b/engine/crates/layerfs-store-service/src/operator/dispatch.rs similarity index 100% rename from core/crates/layerfs-store-service/src/operator/dispatch.rs rename to engine/crates/layerfs-store-service/src/operator/dispatch.rs diff --git a/core/crates/layerfs-store-service/src/operator/files.rs b/engine/crates/layerfs-store-service/src/operator/files.rs similarity index 100% rename from core/crates/layerfs-store-service/src/operator/files.rs rename to engine/crates/layerfs-store-service/src/operator/files.rs diff --git a/core/crates/layerfs-store-service/src/operator/inspect.rs b/engine/crates/layerfs-store-service/src/operator/inspect.rs similarity index 100% rename from core/crates/layerfs-store-service/src/operator/inspect.rs rename to engine/crates/layerfs-store-service/src/operator/inspect.rs diff --git a/core/crates/layerfs-store-service/src/operator/mod.rs b/engine/crates/layerfs-store-service/src/operator/mod.rs similarity index 100% rename from core/crates/layerfs-store-service/src/operator/mod.rs rename to engine/crates/layerfs-store-service/src/operator/mod.rs diff --git a/core/crates/layerfs-store-service/src/operator/store.rs b/engine/crates/layerfs-store-service/src/operator/store.rs similarity index 100% rename from core/crates/layerfs-store-service/src/operator/store.rs rename to engine/crates/layerfs-store-service/src/operator/store.rs diff --git a/core/crates/layerfs-store-service/src/overlay/backing.rs b/engine/crates/layerfs-store-service/src/overlay/backing.rs similarity index 100% rename from core/crates/layerfs-store-service/src/overlay/backing.rs rename to engine/crates/layerfs-store-service/src/overlay/backing.rs diff --git a/core/crates/layerfs-store-service/src/overlay/captured_namespace_port.rs b/engine/crates/layerfs-store-service/src/overlay/captured_namespace_port.rs similarity index 100% rename from core/crates/layerfs-store-service/src/overlay/captured_namespace_port.rs rename to engine/crates/layerfs-store-service/src/overlay/captured_namespace_port.rs diff --git a/core/crates/layerfs-store-service/src/overlay/captured_run_port.rs b/engine/crates/layerfs-store-service/src/overlay/captured_run_port.rs similarity index 100% rename from core/crates/layerfs-store-service/src/overlay/captured_run_port.rs rename to engine/crates/layerfs-store-service/src/overlay/captured_run_port.rs diff --git a/core/crates/layerfs-store-service/src/overlay/file_port.rs b/engine/crates/layerfs-store-service/src/overlay/file_port.rs similarity index 100% rename from core/crates/layerfs-store-service/src/overlay/file_port.rs rename to engine/crates/layerfs-store-service/src/overlay/file_port.rs diff --git a/core/crates/layerfs-store-service/src/overlay/kernel_operations.rs b/engine/crates/layerfs-store-service/src/overlay/kernel_operations.rs similarity index 100% rename from core/crates/layerfs-store-service/src/overlay/kernel_operations.rs rename to engine/crates/layerfs-store-service/src/overlay/kernel_operations.rs diff --git a/core/crates/layerfs-store-service/src/overlay/lifetime_operations.rs b/engine/crates/layerfs-store-service/src/overlay/lifetime_operations.rs similarity index 100% rename from core/crates/layerfs-store-service/src/overlay/lifetime_operations.rs rename to engine/crates/layerfs-store-service/src/overlay/lifetime_operations.rs diff --git a/core/crates/layerfs-store-service/src/overlay/mod.rs b/engine/crates/layerfs-store-service/src/overlay/mod.rs similarity index 100% rename from core/crates/layerfs-store-service/src/overlay/mod.rs rename to engine/crates/layerfs-store-service/src/overlay/mod.rs diff --git a/core/crates/layerfs-store-service/src/overlay/operation_record_port.rs b/engine/crates/layerfs-store-service/src/overlay/operation_record_port.rs similarity index 100% rename from core/crates/layerfs-store-service/src/overlay/operation_record_port.rs rename to engine/crates/layerfs-store-service/src/overlay/operation_record_port.rs diff --git a/core/crates/layerfs-store-service/src/overlay/owner.rs b/engine/crates/layerfs-store-service/src/overlay/owner.rs similarity index 100% rename from core/crates/layerfs-store-service/src/overlay/owner.rs rename to engine/crates/layerfs-store-service/src/overlay/owner.rs diff --git a/core/crates/layerfs-store-service/src/overlay/read_operations.rs b/engine/crates/layerfs-store-service/src/overlay/read_operations.rs similarity index 100% rename from core/crates/layerfs-store-service/src/overlay/read_operations.rs rename to engine/crates/layerfs-store-service/src/overlay/read_operations.rs diff --git a/core/crates/layerfs-store-service/src/overlay/read_port.rs b/engine/crates/layerfs-store-service/src/overlay/read_port.rs similarity index 100% rename from core/crates/layerfs-store-service/src/overlay/read_port.rs rename to engine/crates/layerfs-store-service/src/overlay/read_port.rs diff --git a/core/crates/layerfs-store-service/src/overlay/scopes.rs b/engine/crates/layerfs-store-service/src/overlay/scopes.rs similarity index 100% rename from core/crates/layerfs-store-service/src/overlay/scopes.rs rename to engine/crates/layerfs-store-service/src/overlay/scopes.rs diff --git a/core/crates/layerfs-store-service/src/overlay/state.rs b/engine/crates/layerfs-store-service/src/overlay/state.rs similarity index 100% rename from core/crates/layerfs-store-service/src/overlay/state.rs rename to engine/crates/layerfs-store-service/src/overlay/state.rs diff --git a/core/crates/layerfs-store-service/src/overlay/workspaces.rs b/engine/crates/layerfs-store-service/src/overlay/workspaces.rs similarity index 100% rename from core/crates/layerfs-store-service/src/overlay/workspaces.rs rename to engine/crates/layerfs-store-service/src/overlay/workspaces.rs diff --git a/core/crates/layerfs-store-service/src/read/blame.rs b/engine/crates/layerfs-store-service/src/read/blame.rs similarity index 100% rename from core/crates/layerfs-store-service/src/read/blame.rs rename to engine/crates/layerfs-store-service/src/read/blame.rs diff --git a/core/crates/layerfs-store-service/src/read/cached.rs b/engine/crates/layerfs-store-service/src/read/cached.rs similarity index 100% rename from core/crates/layerfs-store-service/src/read/cached.rs rename to engine/crates/layerfs-store-service/src/read/cached.rs diff --git a/core/crates/layerfs-store-service/src/read/compare.rs b/engine/crates/layerfs-store-service/src/read/compare.rs similarity index 100% rename from core/crates/layerfs-store-service/src/read/compare.rs rename to engine/crates/layerfs-store-service/src/read/compare.rs diff --git a/core/crates/layerfs-store-service/src/read/mod.rs b/engine/crates/layerfs-store-service/src/read/mod.rs similarity index 100% rename from core/crates/layerfs-store-service/src/read/mod.rs rename to engine/crates/layerfs-store-service/src/read/mod.rs diff --git a/core/crates/layerfs-store-service/src/read/plans.rs b/engine/crates/layerfs-store-service/src/read/plans.rs similarity index 100% rename from core/crates/layerfs-store-service/src/read/plans.rs rename to engine/crates/layerfs-store-service/src/read/plans.rs diff --git a/core/crates/layerfs-store-service/src/read/reads.rs b/engine/crates/layerfs-store-service/src/read/reads.rs similarity index 100% rename from core/crates/layerfs-store-service/src/read/reads.rs rename to engine/crates/layerfs-store-service/src/read/reads.rs diff --git a/core/crates/layerfs-store-service/src/read/search.rs b/engine/crates/layerfs-store-service/src/read/search.rs similarity index 100% rename from core/crates/layerfs-store-service/src/read/search.rs rename to engine/crates/layerfs-store-service/src/read/search.rs diff --git a/core/crates/layerfs-store-service/src/read/snapshot.rs b/engine/crates/layerfs-store-service/src/read/snapshot.rs similarity index 100% rename from core/crates/layerfs-store-service/src/read/snapshot.rs rename to engine/crates/layerfs-store-service/src/read/snapshot.rs diff --git a/core/crates/layerfs-store-service/src/read/walk.rs b/engine/crates/layerfs-store-service/src/read/walk.rs similarity index 100% rename from core/crates/layerfs-store-service/src/read/walk.rs rename to engine/crates/layerfs-store-service/src/read/walk.rs diff --git a/core/crates/layerfs-store-service/src/read/window.rs b/engine/crates/layerfs-store-service/src/read/window.rs similarity index 100% rename from core/crates/layerfs-store-service/src/read/window.rs rename to engine/crates/layerfs-store-service/src/read/window.rs diff --git a/core/crates/layerfs-store-service/src/service/mod.rs b/engine/crates/layerfs-store-service/src/service/mod.rs similarity index 100% rename from core/crates/layerfs-store-service/src/service/mod.rs rename to engine/crates/layerfs-store-service/src/service/mod.rs diff --git a/core/crates/layerfs-store-service/src/service/observations.rs b/engine/crates/layerfs-store-service/src/service/observations.rs similarity index 100% rename from core/crates/layerfs-store-service/src/service/observations.rs rename to engine/crates/layerfs-store-service/src/service/observations.rs diff --git a/core/crates/layerfs-store-service/src/service/owner_work.rs b/engine/crates/layerfs-store-service/src/service/owner_work.rs similarity index 100% rename from core/crates/layerfs-store-service/src/service/owner_work.rs rename to engine/crates/layerfs-store-service/src/service/owner_work.rs diff --git a/core/crates/layerfs-store-service/src/service/results.rs b/engine/crates/layerfs-store-service/src/service/results.rs similarity index 100% rename from core/crates/layerfs-store-service/src/service/results.rs rename to engine/crates/layerfs-store-service/src/service/results.rs diff --git a/core/crates/layerfs-store-service/src/service/startup.rs b/engine/crates/layerfs-store-service/src/service/startup.rs similarity index 100% rename from core/crates/layerfs-store-service/src/service/startup.rs rename to engine/crates/layerfs-store-service/src/service/startup.rs diff --git a/core/crates/layerfs-store-service/src/store/bind.rs b/engine/crates/layerfs-store-service/src/store/bind.rs similarity index 100% rename from core/crates/layerfs-store-service/src/store/bind.rs rename to engine/crates/layerfs-store-service/src/store/bind.rs diff --git a/core/crates/layerfs-store-service/src/store/captured.rs b/engine/crates/layerfs-store-service/src/store/captured.rs similarity index 100% rename from core/crates/layerfs-store-service/src/store/captured.rs rename to engine/crates/layerfs-store-service/src/store/captured.rs diff --git a/core/crates/layerfs-store-service/src/store/commit.rs b/engine/crates/layerfs-store-service/src/store/commit.rs similarity index 100% rename from core/crates/layerfs-store-service/src/store/commit.rs rename to engine/crates/layerfs-store-service/src/store/commit.rs diff --git a/core/crates/layerfs-store-service/src/store/commit_merge.rs b/engine/crates/layerfs-store-service/src/store/commit_merge.rs similarity index 100% rename from core/crates/layerfs-store-service/src/store/commit_merge.rs rename to engine/crates/layerfs-store-service/src/store/commit_merge.rs diff --git a/core/crates/layerfs-store-service/src/store/commit_types.rs b/engine/crates/layerfs-store-service/src/store/commit_types.rs similarity index 100% rename from core/crates/layerfs-store-service/src/store/commit_types.rs rename to engine/crates/layerfs-store-service/src/store/commit_types.rs diff --git a/core/crates/layerfs-store-service/src/store/digests.rs b/engine/crates/layerfs-store-service/src/store/digests.rs similarity index 100% rename from core/crates/layerfs-store-service/src/store/digests.rs rename to engine/crates/layerfs-store-service/src/store/digests.rs diff --git a/core/crates/layerfs-store-service/src/store/hints.rs b/engine/crates/layerfs-store-service/src/store/hints.rs similarity index 100% rename from core/crates/layerfs-store-service/src/store/hints.rs rename to engine/crates/layerfs-store-service/src/store/hints.rs diff --git a/core/crates/layerfs-store-service/src/store/mod.rs b/engine/crates/layerfs-store-service/src/store/mod.rs similarity index 100% rename from core/crates/layerfs-store-service/src/store/mod.rs rename to engine/crates/layerfs-store-service/src/store/mod.rs diff --git a/core/crates/layerfs-store-service/src/store/open.rs b/engine/crates/layerfs-store-service/src/store/open.rs similarity index 100% rename from core/crates/layerfs-store-service/src/store/open.rs rename to engine/crates/layerfs-store-service/src/store/open.rs diff --git a/core/crates/layerfs-store-service/src/store/operation.rs b/engine/crates/layerfs-store-service/src/store/operation.rs similarity index 100% rename from core/crates/layerfs-store-service/src/store/operation.rs rename to engine/crates/layerfs-store-service/src/store/operation.rs diff --git a/core/crates/layerfs-store-service/src/store/ports.rs b/engine/crates/layerfs-store-service/src/store/ports.rs similarity index 100% rename from core/crates/layerfs-store-service/src/store/ports.rs rename to engine/crates/layerfs-store-service/src/store/ports.rs diff --git a/core/crates/layerfs-store-service/src/store/producer.rs b/engine/crates/layerfs-store-service/src/store/producer.rs similarity index 100% rename from core/crates/layerfs-store-service/src/store/producer.rs rename to engine/crates/layerfs-store-service/src/store/producer.rs diff --git a/core/crates/layerfs-store-service/src/store/read_handle.rs b/engine/crates/layerfs-store-service/src/store/read_handle.rs similarity index 100% rename from core/crates/layerfs-store-service/src/store/read_handle.rs rename to engine/crates/layerfs-store-service/src/store/read_handle.rs diff --git a/core/crates/layerfs-store-service/src/store/read_service.rs b/engine/crates/layerfs-store-service/src/store/read_service.rs similarity index 100% rename from core/crates/layerfs-store-service/src/store/read_service.rs rename to engine/crates/layerfs-store-service/src/store/read_service.rs diff --git a/core/crates/layerfs-store-service/src/store/recognizer.rs b/engine/crates/layerfs-store-service/src/store/recognizer.rs similarity index 100% rename from core/crates/layerfs-store-service/src/store/recognizer.rs rename to engine/crates/layerfs-store-service/src/store/recognizer.rs diff --git a/core/crates/layerfs-store-service/src/store/settle.rs b/engine/crates/layerfs-store-service/src/store/settle.rs similarity index 100% rename from core/crates/layerfs-store-service/src/store/settle.rs rename to engine/crates/layerfs-store-service/src/store/settle.rs diff --git a/core/crates/layerfs-store-service/src/store/statistics.rs b/engine/crates/layerfs-store-service/src/store/statistics.rs similarity index 100% rename from core/crates/layerfs-store-service/src/store/statistics.rs rename to engine/crates/layerfs-store-service/src/store/statistics.rs diff --git a/core/crates/layerfs-store-service/src/store/types.rs b/engine/crates/layerfs-store-service/src/store/types.rs similarity index 100% rename from core/crates/layerfs-store-service/src/store/types.rs rename to engine/crates/layerfs-store-service/src/store/types.rs diff --git a/core/crates/layerfs-store-service/src/store_service.rs b/engine/crates/layerfs-store-service/src/store_service.rs similarity index 100% rename from core/crates/layerfs-store-service/src/store_service.rs rename to engine/crates/layerfs-store-service/src/store_service.rs diff --git a/core/crates/layerfs-store-service/src/telemetry.rs b/engine/crates/layerfs-store-service/src/telemetry.rs similarity index 100% rename from core/crates/layerfs-store-service/src/telemetry.rs rename to engine/crates/layerfs-store-service/src/telemetry.rs diff --git a/core/crates/layerfs-store-service/src/write/edit.rs b/engine/crates/layerfs-store-service/src/write/edit.rs similarity index 100% rename from core/crates/layerfs-store-service/src/write/edit.rs rename to engine/crates/layerfs-store-service/src/write/edit.rs diff --git a/core/crates/layerfs-store-service/src/write/files.rs b/engine/crates/layerfs-store-service/src/write/files.rs similarity index 100% rename from core/crates/layerfs-store-service/src/write/files.rs rename to engine/crates/layerfs-store-service/src/write/files.rs diff --git a/core/crates/layerfs-store-service/src/write/mod.rs b/engine/crates/layerfs-store-service/src/write/mod.rs similarity index 100% rename from core/crates/layerfs-store-service/src/write/mod.rs rename to engine/crates/layerfs-store-service/src/write/mod.rs diff --git a/core/crates/layerfs-store-service/src/write/mutation.rs b/engine/crates/layerfs-store-service/src/write/mutation.rs similarity index 100% rename from core/crates/layerfs-store-service/src/write/mutation.rs rename to engine/crates/layerfs-store-service/src/write/mutation.rs diff --git a/core/crates/layerfs-store-service/src/write/recursive.rs b/engine/crates/layerfs-store-service/src/write/recursive.rs similarity index 100% rename from core/crates/layerfs-store-service/src/write/recursive.rs rename to engine/crates/layerfs-store-service/src/write/recursive.rs diff --git a/core/crates/layerfs-store-service/tests/kept_plans.rs b/engine/crates/layerfs-store-service/tests/kept_plans.rs similarity index 100% rename from core/crates/layerfs-store-service/tests/kept_plans.rs rename to engine/crates/layerfs-store-service/tests/kept_plans.rs diff --git a/core/crates/layerfs-store-service/tests/kernel_guard.rs b/engine/crates/layerfs-store-service/tests/kernel_guard.rs similarity index 100% rename from core/crates/layerfs-store-service/tests/kernel_guard.rs rename to engine/crates/layerfs-store-service/tests/kernel_guard.rs diff --git a/core/crates/layerfs-store-service/tests/sdk_root_batches.rs b/engine/crates/layerfs-store-service/tests/sdk_root_batches.rs similarity index 100% rename from core/crates/layerfs-store-service/tests/sdk_root_batches.rs rename to engine/crates/layerfs-store-service/tests/sdk_root_batches.rs diff --git a/core/crates/layerfs-workspace/Cargo.toml b/engine/crates/layerfs-workspace/Cargo.toml similarity index 72% rename from core/crates/layerfs-workspace/Cargo.toml rename to engine/crates/layerfs-workspace/Cargo.toml index c2014c912..d0b0bd863 100644 --- a/core/crates/layerfs-workspace/Cargo.toml +++ b/engine/crates/layerfs-workspace/Cargo.toml @@ -7,9 +7,9 @@ rust-version.workspace = true license.workspace = true [dependencies] -layerfs-content = { path = "../layerfs-content" } +layerfs-content = { path = "../../../core/crates/layerfs-content" } layerfs-overlay = { path = "../layerfs-overlay" } -layerfs-telemetry = { path = "../layerfs-telemetry" } +layerfs-telemetry = { path = "../../../core/crates/layerfs-telemetry" } [dev-dependencies] layerfs-daemon = { path = "../layerfs-daemon" } diff --git a/core/crates/layerfs-workspace/src/base/cache.rs b/engine/crates/layerfs-workspace/src/base/cache.rs similarity index 100% rename from core/crates/layerfs-workspace/src/base/cache.rs rename to engine/crates/layerfs-workspace/src/base/cache.rs diff --git a/core/crates/layerfs-workspace/src/base/client.rs b/engine/crates/layerfs-workspace/src/base/client.rs similarity index 100% rename from core/crates/layerfs-workspace/src/base/client.rs rename to engine/crates/layerfs-workspace/src/base/client.rs diff --git a/core/crates/layerfs-workspace/src/base/file.rs b/engine/crates/layerfs-workspace/src/base/file.rs similarity index 100% rename from core/crates/layerfs-workspace/src/base/file.rs rename to engine/crates/layerfs-workspace/src/base/file.rs diff --git a/core/crates/layerfs-workspace/src/base/links.rs b/engine/crates/layerfs-workspace/src/base/links.rs similarity index 100% rename from core/crates/layerfs-workspace/src/base/links.rs rename to engine/crates/layerfs-workspace/src/base/links.rs diff --git a/core/crates/layerfs-workspace/src/base/mod.rs b/engine/crates/layerfs-workspace/src/base/mod.rs similarity index 100% rename from core/crates/layerfs-workspace/src/base/mod.rs rename to engine/crates/layerfs-workspace/src/base/mod.rs diff --git a/core/crates/layerfs-workspace/src/base/view.rs b/engine/crates/layerfs-workspace/src/base/view.rs similarity index 100% rename from core/crates/layerfs-workspace/src/base/view.rs rename to engine/crates/layerfs-workspace/src/base/view.rs diff --git a/core/crates/layerfs-workspace/src/construction/captured/context.rs b/engine/crates/layerfs-workspace/src/construction/captured/context.rs similarity index 100% rename from core/crates/layerfs-workspace/src/construction/captured/context.rs rename to engine/crates/layerfs-workspace/src/construction/captured/context.rs diff --git a/core/crates/layerfs-workspace/src/construction/captured/edges.rs b/engine/crates/layerfs-workspace/src/construction/captured/edges.rs similarity index 100% rename from core/crates/layerfs-workspace/src/construction/captured/edges.rs rename to engine/crates/layerfs-workspace/src/construction/captured/edges.rs diff --git a/core/crates/layerfs-workspace/src/construction/captured/mod.rs b/engine/crates/layerfs-workspace/src/construction/captured/mod.rs similarity index 100% rename from core/crates/layerfs-workspace/src/construction/captured/mod.rs rename to engine/crates/layerfs-workspace/src/construction/captured/mod.rs diff --git a/core/crates/layerfs-workspace/src/construction/captured/normalize.rs b/engine/crates/layerfs-workspace/src/construction/captured/normalize.rs similarity index 100% rename from core/crates/layerfs-workspace/src/construction/captured/normalize.rs rename to engine/crates/layerfs-workspace/src/construction/captured/normalize.rs diff --git a/core/crates/layerfs-workspace/src/construction/captured/owner.rs b/engine/crates/layerfs-workspace/src/construction/captured/owner.rs similarity index 100% rename from core/crates/layerfs-workspace/src/construction/captured/owner.rs rename to engine/crates/layerfs-workspace/src/construction/captured/owner.rs diff --git a/core/crates/layerfs-workspace/src/construction/captured/scan.rs b/engine/crates/layerfs-workspace/src/construction/captured/scan.rs similarity index 100% rename from core/crates/layerfs-workspace/src/construction/captured/scan.rs rename to engine/crates/layerfs-workspace/src/construction/captured/scan.rs diff --git a/core/crates/layerfs-workspace/src/construction/captured/script.rs b/engine/crates/layerfs-workspace/src/construction/captured/script.rs similarity index 100% rename from core/crates/layerfs-workspace/src/construction/captured/script.rs rename to engine/crates/layerfs-workspace/src/construction/captured/script.rs diff --git a/core/crates/layerfs-workspace/src/construction/captured/source.rs b/engine/crates/layerfs-workspace/src/construction/captured/source.rs similarity index 100% rename from core/crates/layerfs-workspace/src/construction/captured/source.rs rename to engine/crates/layerfs-workspace/src/construction/captured/source.rs diff --git a/core/crates/layerfs-workspace/src/construction/captured/state.rs b/engine/crates/layerfs-workspace/src/construction/captured/state.rs similarity index 100% rename from core/crates/layerfs-workspace/src/construction/captured/state.rs rename to engine/crates/layerfs-workspace/src/construction/captured/state.rs diff --git a/core/crates/layerfs-workspace/src/construction/driver.rs b/engine/crates/layerfs-workspace/src/construction/driver.rs similarity index 100% rename from core/crates/layerfs-workspace/src/construction/driver.rs rename to engine/crates/layerfs-workspace/src/construction/driver.rs diff --git a/core/crates/layerfs-workspace/src/construction/mod.rs b/engine/crates/layerfs-workspace/src/construction/mod.rs similarity index 100% rename from core/crates/layerfs-workspace/src/construction/mod.rs rename to engine/crates/layerfs-workspace/src/construction/mod.rs diff --git a/core/crates/layerfs-workspace/src/construction/namespace/cursor.rs b/engine/crates/layerfs-workspace/src/construction/namespace/cursor.rs similarity index 100% rename from core/crates/layerfs-workspace/src/construction/namespace/cursor.rs rename to engine/crates/layerfs-workspace/src/construction/namespace/cursor.rs diff --git a/core/crates/layerfs-workspace/src/construction/namespace/inodes.rs b/engine/crates/layerfs-workspace/src/construction/namespace/inodes.rs similarity index 100% rename from core/crates/layerfs-workspace/src/construction/namespace/inodes.rs rename to engine/crates/layerfs-workspace/src/construction/namespace/inodes.rs diff --git a/core/crates/layerfs-workspace/src/construction/namespace/mod.rs b/engine/crates/layerfs-workspace/src/construction/namespace/mod.rs similarity index 100% rename from core/crates/layerfs-workspace/src/construction/namespace/mod.rs rename to engine/crates/layerfs-workspace/src/construction/namespace/mod.rs diff --git a/core/crates/layerfs-workspace/src/construction/namespace/normalize.rs b/engine/crates/layerfs-workspace/src/construction/namespace/normalize.rs similarity index 100% rename from core/crates/layerfs-workspace/src/construction/namespace/normalize.rs rename to engine/crates/layerfs-workspace/src/construction/namespace/normalize.rs diff --git a/core/crates/layerfs-workspace/src/construction/namespace/records.rs b/engine/crates/layerfs-workspace/src/construction/namespace/records.rs similarity index 100% rename from core/crates/layerfs-workspace/src/construction/namespace/records.rs rename to engine/crates/layerfs-workspace/src/construction/namespace/records.rs diff --git a/core/crates/layerfs-workspace/src/construction/outcome.rs b/engine/crates/layerfs-workspace/src/construction/outcome.rs similarity index 100% rename from core/crates/layerfs-workspace/src/construction/outcome.rs rename to engine/crates/layerfs-workspace/src/construction/outcome.rs diff --git a/core/crates/layerfs-workspace/src/construction/records.rs b/engine/crates/layerfs-workspace/src/construction/records.rs similarity index 100% rename from core/crates/layerfs-workspace/src/construction/records.rs rename to engine/crates/layerfs-workspace/src/construction/records.rs diff --git a/core/crates/layerfs-workspace/src/lib.rs b/engine/crates/layerfs-workspace/src/lib.rs similarity index 100% rename from core/crates/layerfs-workspace/src/lib.rs rename to engine/crates/layerfs-workspace/src/lib.rs diff --git a/core/crates/layerfs-workspace/src/mutation/driver.rs b/engine/crates/layerfs-workspace/src/mutation/driver.rs similarity index 100% rename from core/crates/layerfs-workspace/src/mutation/driver.rs rename to engine/crates/layerfs-workspace/src/mutation/driver.rs diff --git a/core/crates/layerfs-workspace/src/mutation/eval.rs b/engine/crates/layerfs-workspace/src/mutation/eval.rs similarity index 100% rename from core/crates/layerfs-workspace/src/mutation/eval.rs rename to engine/crates/layerfs-workspace/src/mutation/eval.rs diff --git a/core/crates/layerfs-workspace/src/mutation/facts.rs b/engine/crates/layerfs-workspace/src/mutation/facts.rs similarity index 100% rename from core/crates/layerfs-workspace/src/mutation/facts.rs rename to engine/crates/layerfs-workspace/src/mutation/facts.rs diff --git a/core/crates/layerfs-workspace/src/mutation/job.rs b/engine/crates/layerfs-workspace/src/mutation/job.rs similarity index 100% rename from core/crates/layerfs-workspace/src/mutation/job.rs rename to engine/crates/layerfs-workspace/src/mutation/job.rs diff --git a/core/crates/layerfs-workspace/src/mutation/mod.rs b/engine/crates/layerfs-workspace/src/mutation/mod.rs similarity index 100% rename from core/crates/layerfs-workspace/src/mutation/mod.rs rename to engine/crates/layerfs-workspace/src/mutation/mod.rs diff --git a/core/crates/layerfs-workspace/src/mutation/plan.rs b/engine/crates/layerfs-workspace/src/mutation/plan.rs similarity index 100% rename from core/crates/layerfs-workspace/src/mutation/plan.rs rename to engine/crates/layerfs-workspace/src/mutation/plan.rs diff --git a/core/crates/layerfs-workspace/src/operations/attributes.rs b/engine/crates/layerfs-workspace/src/operations/attributes.rs similarity index 100% rename from core/crates/layerfs-workspace/src/operations/attributes.rs rename to engine/crates/layerfs-workspace/src/operations/attributes.rs diff --git a/core/crates/layerfs-workspace/src/operations/file/mod.rs b/engine/crates/layerfs-workspace/src/operations/file/mod.rs similarity index 100% rename from core/crates/layerfs-workspace/src/operations/file/mod.rs rename to engine/crates/layerfs-workspace/src/operations/file/mod.rs diff --git a/core/crates/layerfs-workspace/src/operations/file/read.rs b/engine/crates/layerfs-workspace/src/operations/file/read.rs similarity index 100% rename from core/crates/layerfs-workspace/src/operations/file/read.rs rename to engine/crates/layerfs-workspace/src/operations/file/read.rs diff --git a/core/crates/layerfs-workspace/src/operations/file/recognize.rs b/engine/crates/layerfs-workspace/src/operations/file/recognize.rs similarity index 100% rename from core/crates/layerfs-workspace/src/operations/file/recognize.rs rename to engine/crates/layerfs-workspace/src/operations/file/recognize.rs diff --git a/core/crates/layerfs-workspace/src/operations/file/write.rs b/engine/crates/layerfs-workspace/src/operations/file/write.rs similarity index 100% rename from core/crates/layerfs-workspace/src/operations/file/write.rs rename to engine/crates/layerfs-workspace/src/operations/file/write.rs diff --git a/core/crates/layerfs-workspace/src/operations/kernel_data.rs b/engine/crates/layerfs-workspace/src/operations/kernel_data.rs similarity index 100% rename from core/crates/layerfs-workspace/src/operations/kernel_data.rs rename to engine/crates/layerfs-workspace/src/operations/kernel_data.rs diff --git a/core/crates/layerfs-workspace/src/operations/kernel_directory.rs b/engine/crates/layerfs-workspace/src/operations/kernel_directory.rs similarity index 100% rename from core/crates/layerfs-workspace/src/operations/kernel_directory.rs rename to engine/crates/layerfs-workspace/src/operations/kernel_directory.rs diff --git a/core/crates/layerfs-workspace/src/operations/kernel_mutation.rs b/engine/crates/layerfs-workspace/src/operations/kernel_mutation.rs similarity index 100% rename from core/crates/layerfs-workspace/src/operations/kernel_mutation.rs rename to engine/crates/layerfs-workspace/src/operations/kernel_mutation.rs diff --git a/core/crates/layerfs-workspace/src/operations/kernel_read.rs b/engine/crates/layerfs-workspace/src/operations/kernel_read.rs similarity index 100% rename from core/crates/layerfs-workspace/src/operations/kernel_read.rs rename to engine/crates/layerfs-workspace/src/operations/kernel_read.rs diff --git a/core/crates/layerfs-workspace/src/operations/kernel_visit.rs b/engine/crates/layerfs-workspace/src/operations/kernel_visit.rs similarity index 100% rename from core/crates/layerfs-workspace/src/operations/kernel_visit.rs rename to engine/crates/layerfs-workspace/src/operations/kernel_visit.rs diff --git a/core/crates/layerfs-workspace/src/operations/mod.rs b/engine/crates/layerfs-workspace/src/operations/mod.rs similarity index 100% rename from core/crates/layerfs-workspace/src/operations/mod.rs rename to engine/crates/layerfs-workspace/src/operations/mod.rs diff --git a/core/crates/layerfs-workspace/src/operations/namespace/create.rs b/engine/crates/layerfs-workspace/src/operations/namespace/create.rs similarity index 100% rename from core/crates/layerfs-workspace/src/operations/namespace/create.rs rename to engine/crates/layerfs-workspace/src/operations/namespace/create.rs diff --git a/core/crates/layerfs-workspace/src/operations/namespace/list.rs b/engine/crates/layerfs-workspace/src/operations/namespace/list.rs similarity index 100% rename from core/crates/layerfs-workspace/src/operations/namespace/list.rs rename to engine/crates/layerfs-workspace/src/operations/namespace/list.rs diff --git a/core/crates/layerfs-workspace/src/operations/namespace/mod.rs b/engine/crates/layerfs-workspace/src/operations/namespace/mod.rs similarity index 100% rename from core/crates/layerfs-workspace/src/operations/namespace/mod.rs rename to engine/crates/layerfs-workspace/src/operations/namespace/mod.rs diff --git a/core/crates/layerfs-workspace/src/operations/namespace/remove.rs b/engine/crates/layerfs-workspace/src/operations/namespace/remove.rs similarity index 100% rename from core/crates/layerfs-workspace/src/operations/namespace/remove.rs rename to engine/crates/layerfs-workspace/src/operations/namespace/remove.rs diff --git a/core/crates/layerfs-workspace/src/operations/namespace/rename.rs b/engine/crates/layerfs-workspace/src/operations/namespace/rename.rs similarity index 100% rename from core/crates/layerfs-workspace/src/operations/namespace/rename.rs rename to engine/crates/layerfs-workspace/src/operations/namespace/rename.rs diff --git a/core/crates/layerfs-workspace/src/operations/types.rs b/engine/crates/layerfs-workspace/src/operations/types.rs similarity index 100% rename from core/crates/layerfs-workspace/src/operations/types.rs rename to engine/crates/layerfs-workspace/src/operations/types.rs diff --git a/core/crates/layerfs-workspace/src/ports/captured_namespace.rs b/engine/crates/layerfs-workspace/src/ports/captured_namespace.rs similarity index 100% rename from core/crates/layerfs-workspace/src/ports/captured_namespace.rs rename to engine/crates/layerfs-workspace/src/ports/captured_namespace.rs diff --git a/core/crates/layerfs-workspace/src/ports/captured_runs.rs b/engine/crates/layerfs-workspace/src/ports/captured_runs.rs similarity index 100% rename from core/crates/layerfs-workspace/src/ports/captured_runs.rs rename to engine/crates/layerfs-workspace/src/ports/captured_runs.rs diff --git a/core/crates/layerfs-workspace/src/ports/digests.rs b/engine/crates/layerfs-workspace/src/ports/digests.rs similarity index 100% rename from core/crates/layerfs-workspace/src/ports/digests.rs rename to engine/crates/layerfs-workspace/src/ports/digests.rs diff --git a/core/crates/layerfs-workspace/src/ports/files.rs b/engine/crates/layerfs-workspace/src/ports/files.rs similarity index 100% rename from core/crates/layerfs-workspace/src/ports/files.rs rename to engine/crates/layerfs-workspace/src/ports/files.rs diff --git a/core/crates/layerfs-workspace/src/ports/lengths.rs b/engine/crates/layerfs-workspace/src/ports/lengths.rs similarity index 100% rename from core/crates/layerfs-workspace/src/ports/lengths.rs rename to engine/crates/layerfs-workspace/src/ports/lengths.rs diff --git a/core/crates/layerfs-workspace/src/ports/mod.rs b/engine/crates/layerfs-workspace/src/ports/mod.rs similarity index 100% rename from core/crates/layerfs-workspace/src/ports/mod.rs rename to engine/crates/layerfs-workspace/src/ports/mod.rs diff --git a/core/crates/layerfs-workspace/src/ports/operation_record.rs b/engine/crates/layerfs-workspace/src/ports/operation_record.rs similarity index 100% rename from core/crates/layerfs-workspace/src/ports/operation_record.rs rename to engine/crates/layerfs-workspace/src/ports/operation_record.rs diff --git a/core/crates/layerfs-workspace/src/ports/overlay.rs b/engine/crates/layerfs-workspace/src/ports/overlay.rs similarity index 100% rename from core/crates/layerfs-workspace/src/ports/overlay.rs rename to engine/crates/layerfs-workspace/src/ports/overlay.rs diff --git a/core/crates/layerfs-workspace/src/workspace/install.rs b/engine/crates/layerfs-workspace/src/workspace/install.rs similarity index 100% rename from core/crates/layerfs-workspace/src/workspace/install.rs rename to engine/crates/layerfs-workspace/src/workspace/install.rs diff --git a/core/crates/layerfs-workspace/src/workspace/mod.rs b/engine/crates/layerfs-workspace/src/workspace/mod.rs similarity index 100% rename from core/crates/layerfs-workspace/src/workspace/mod.rs rename to engine/crates/layerfs-workspace/src/workspace/mod.rs diff --git a/core/crates/layerfs-workspace/src/workspace/route.rs b/engine/crates/layerfs-workspace/src/workspace/route.rs similarity index 100% rename from core/crates/layerfs-workspace/src/workspace/route.rs rename to engine/crates/layerfs-workspace/src/workspace/route.rs diff --git a/core/crates/layerfs-workspace/src/workspace/serials.rs b/engine/crates/layerfs-workspace/src/workspace/serials.rs similarity index 100% rename from core/crates/layerfs-workspace/src/workspace/serials.rs rename to engine/crates/layerfs-workspace/src/workspace/serials.rs diff --git a/core/crates/layerfs-workspace/src/workspace/state.rs b/engine/crates/layerfs-workspace/src/workspace/state.rs similarity index 100% rename from core/crates/layerfs-workspace/src/workspace/state.rs rename to engine/crates/layerfs-workspace/src/workspace/state.rs diff --git a/core/crates/layerfs-workspace/src/workspace/view.rs b/engine/crates/layerfs-workspace/src/workspace/view.rs similarity index 100% rename from core/crates/layerfs-workspace/src/workspace/view.rs rename to engine/crates/layerfs-workspace/src/workspace/view.rs diff --git a/core/crates/layerfs-workspace/tests/captured_file_edits.rs b/engine/crates/layerfs-workspace/tests/captured_file_edits.rs similarity index 100% rename from core/crates/layerfs-workspace/tests/captured_file_edits.rs rename to engine/crates/layerfs-workspace/tests/captured_file_edits.rs diff --git a/core/crates/layerfs-workspace/tests/captured_namespace.rs b/engine/crates/layerfs-workspace/tests/captured_namespace.rs similarity index 100% rename from core/crates/layerfs-workspace/tests/captured_namespace.rs rename to engine/crates/layerfs-workspace/tests/captured_namespace.rs diff --git a/core/crates/layerfs-workspace/tests/captured_namespace_cursor.rs b/engine/crates/layerfs-workspace/tests/captured_namespace_cursor.rs similarity index 100% rename from core/crates/layerfs-workspace/tests/captured_namespace_cursor.rs rename to engine/crates/layerfs-workspace/tests/captured_namespace_cursor.rs diff --git a/core/crates/layerfs-workspace/tests/captured_namespace_custody.rs b/engine/crates/layerfs-workspace/tests/captured_namespace_custody.rs similarity index 100% rename from core/crates/layerfs-workspace/tests/captured_namespace_custody.rs rename to engine/crates/layerfs-workspace/tests/captured_namespace_custody.rs diff --git a/core/crates/layerfs-workspace/tests/captured_namespace_fragments.rs b/engine/crates/layerfs-workspace/tests/captured_namespace_fragments.rs similarity index 100% rename from core/crates/layerfs-workspace/tests/captured_namespace_fragments.rs rename to engine/crates/layerfs-workspace/tests/captured_namespace_fragments.rs diff --git a/core/crates/layerfs-workspace/tests/captured_namespace_holds.rs b/engine/crates/layerfs-workspace/tests/captured_namespace_holds.rs similarity index 100% rename from core/crates/layerfs-workspace/tests/captured_namespace_holds.rs rename to engine/crates/layerfs-workspace/tests/captured_namespace_holds.rs diff --git a/core/crates/layerfs-workspace/tests/captured_namespace_inline.rs b/engine/crates/layerfs-workspace/tests/captured_namespace_inline.rs similarity index 100% rename from core/crates/layerfs-workspace/tests/captured_namespace_inline.rs rename to engine/crates/layerfs-workspace/tests/captured_namespace_inline.rs diff --git a/core/crates/layerfs-workspace/tests/captured_namespace_metadata.rs b/engine/crates/layerfs-workspace/tests/captured_namespace_metadata.rs similarity index 100% rename from core/crates/layerfs-workspace/tests/captured_namespace_metadata.rs rename to engine/crates/layerfs-workspace/tests/captured_namespace_metadata.rs diff --git a/core/crates/layerfs-workspace/tests/captured_namespace_order.rs b/engine/crates/layerfs-workspace/tests/captured_namespace_order.rs similarity index 100% rename from core/crates/layerfs-workspace/tests/captured_namespace_order.rs rename to engine/crates/layerfs-workspace/tests/captured_namespace_order.rs diff --git a/core/crates/layerfs-workspace/tests/captured_namespace_perturbed.rs b/engine/crates/layerfs-workspace/tests/captured_namespace_perturbed.rs similarity index 100% rename from core/crates/layerfs-workspace/tests/captured_namespace_perturbed.rs rename to engine/crates/layerfs-workspace/tests/captured_namespace_perturbed.rs diff --git a/core/crates/layerfs-workspace/tests/captured_namespace_rebound.rs b/engine/crates/layerfs-workspace/tests/captured_namespace_rebound.rs similarity index 100% rename from core/crates/layerfs-workspace/tests/captured_namespace_rebound.rs rename to engine/crates/layerfs-workspace/tests/captured_namespace_rebound.rs diff --git a/core/crates/layerfs-workspace/tests/captured_namespace_states.rs b/engine/crates/layerfs-workspace/tests/captured_namespace_states.rs similarity index 100% rename from core/crates/layerfs-workspace/tests/captured_namespace_states.rs rename to engine/crates/layerfs-workspace/tests/captured_namespace_states.rs diff --git a/core/crates/layerfs-workspace/tests/captured_new_file_route.rs b/engine/crates/layerfs-workspace/tests/captured_new_file_route.rs similarity index 100% rename from core/crates/layerfs-workspace/tests/captured_new_file_route.rs rename to engine/crates/layerfs-workspace/tests/captured_new_file_route.rs diff --git a/core/crates/layerfs-workspace/tests/captured_piece_edits.rs b/engine/crates/layerfs-workspace/tests/captured_piece_edits.rs similarity index 100% rename from core/crates/layerfs-workspace/tests/captured_piece_edits.rs rename to engine/crates/layerfs-workspace/tests/captured_piece_edits.rs diff --git a/core/crates/layerfs-workspace/tests/captured_support/mod.rs b/engine/crates/layerfs-workspace/tests/captured_support/mod.rs similarity index 100% rename from core/crates/layerfs-workspace/tests/captured_support/mod.rs rename to engine/crates/layerfs-workspace/tests/captured_support/mod.rs diff --git a/core/crates/layerfs-workspace/tests/common/mod.rs b/engine/crates/layerfs-workspace/tests/common/mod.rs similarity index 100% rename from core/crates/layerfs-workspace/tests/common/mod.rs rename to engine/crates/layerfs-workspace/tests/common/mod.rs diff --git a/core/crates/layerfs-workspace/tests/decoded_pages.rs b/engine/crates/layerfs-workspace/tests/decoded_pages.rs similarity index 100% rename from core/crates/layerfs-workspace/tests/decoded_pages.rs rename to engine/crates/layerfs-workspace/tests/decoded_pages.rs diff --git a/core/crates/layerfs-workspace/tests/directory_links.rs b/engine/crates/layerfs-workspace/tests/directory_links.rs similarity index 100% rename from core/crates/layerfs-workspace/tests/directory_links.rs rename to engine/crates/layerfs-workspace/tests/directory_links.rs diff --git a/core/crates/layerfs-workspace/tests/directory_links_install.rs b/engine/crates/layerfs-workspace/tests/directory_links_install.rs similarity index 100% rename from core/crates/layerfs-workspace/tests/directory_links_install.rs rename to engine/crates/layerfs-workspace/tests/directory_links_install.rs diff --git a/core/crates/layerfs-workspace/tests/file_lengths.rs b/engine/crates/layerfs-workspace/tests/file_lengths.rs similarity index 100% rename from core/crates/layerfs-workspace/tests/file_lengths.rs rename to engine/crates/layerfs-workspace/tests/file_lengths.rs diff --git a/core/crates/layerfs-workspace/tests/harness/mod.rs b/engine/crates/layerfs-workspace/tests/harness/mod.rs similarity index 100% rename from core/crates/layerfs-workspace/tests/harness/mod.rs rename to engine/crates/layerfs-workspace/tests/harness/mod.rs diff --git a/core/crates/layerfs-workspace/tests/kernel_data.rs b/engine/crates/layerfs-workspace/tests/kernel_data.rs similarity index 100% rename from core/crates/layerfs-workspace/tests/kernel_data.rs rename to engine/crates/layerfs-workspace/tests/kernel_data.rs diff --git a/core/crates/layerfs-workspace/tests/kernel_directory.rs b/engine/crates/layerfs-workspace/tests/kernel_directory.rs similarity index 100% rename from core/crates/layerfs-workspace/tests/kernel_directory.rs rename to engine/crates/layerfs-workspace/tests/kernel_directory.rs diff --git a/core/crates/layerfs-workspace/tests/kernel_visit.rs b/engine/crates/layerfs-workspace/tests/kernel_visit.rs similarity index 100% rename from core/crates/layerfs-workspace/tests/kernel_visit.rs rename to engine/crates/layerfs-workspace/tests/kernel_visit.rs diff --git a/core/crates/layerfs-workspace/tests/mutation_plan.rs b/engine/crates/layerfs-workspace/tests/mutation_plan.rs similarity index 100% rename from core/crates/layerfs-workspace/tests/mutation_plan.rs rename to engine/crates/layerfs-workspace/tests/mutation_plan.rs diff --git a/core/crates/layerfs-workspace/tests/namespace.rs b/engine/crates/layerfs-workspace/tests/namespace.rs similarity index 100% rename from core/crates/layerfs-workspace/tests/namespace.rs rename to engine/crates/layerfs-workspace/tests/namespace.rs diff --git a/core/crates/layerfs-workspace/tests/namespace_view.rs b/engine/crates/layerfs-workspace/tests/namespace_view.rs similarity index 100% rename from core/crates/layerfs-workspace/tests/namespace_view.rs rename to engine/crates/layerfs-workspace/tests/namespace_view.rs diff --git a/core/crates/layerfs-workspace/tests/nonfile.rs b/engine/crates/layerfs-workspace/tests/nonfile.rs similarity index 100% rename from core/crates/layerfs-workspace/tests/nonfile.rs rename to engine/crates/layerfs-workspace/tests/nonfile.rs diff --git a/core/crates/layerfs-workspace/tests/operation_scope.rs b/engine/crates/layerfs-workspace/tests/operation_scope.rs similarity index 100% rename from core/crates/layerfs-workspace/tests/operation_scope.rs rename to engine/crates/layerfs-workspace/tests/operation_scope.rs diff --git a/core/crates/layerfs-workspace/tests/oracle/mod.rs b/engine/crates/layerfs-workspace/tests/oracle/mod.rs similarity index 100% rename from core/crates/layerfs-workspace/tests/oracle/mod.rs rename to engine/crates/layerfs-workspace/tests/oracle/mod.rs diff --git a/core/crates/layerfs-workspace/tests/payload.rs b/engine/crates/layerfs-workspace/tests/payload.rs similarity index 100% rename from core/crates/layerfs-workspace/tests/payload.rs rename to engine/crates/layerfs-workspace/tests/payload.rs diff --git a/core/crates/layerfs-workspace/tests/producer/mod.rs b/engine/crates/layerfs-workspace/tests/producer/mod.rs similarity index 100% rename from core/crates/layerfs-workspace/tests/producer/mod.rs rename to engine/crates/layerfs-workspace/tests/producer/mod.rs diff --git a/core/crates/layerfs-workspace/tests/recognize.rs b/engine/crates/layerfs-workspace/tests/recognize.rs similarity index 100% rename from core/crates/layerfs-workspace/tests/recognize.rs rename to engine/crates/layerfs-workspace/tests/recognize.rs diff --git a/core/crates/layerfs-workspace/tests/shared_cache_client.rs b/engine/crates/layerfs-workspace/tests/shared_cache_client.rs similarity index 100% rename from core/crates/layerfs-workspace/tests/shared_cache_client.rs rename to engine/crates/layerfs-workspace/tests/shared_cache_client.rs diff --git a/core/crates/layerfs-workspace/tests/sibling_lengths.rs b/engine/crates/layerfs-workspace/tests/sibling_lengths.rs similarity index 100% rename from core/crates/layerfs-workspace/tests/sibling_lengths.rs rename to engine/crates/layerfs-workspace/tests/sibling_lengths.rs diff --git a/core/patches/fuser-0.18.0/README.md b/engine/patches/fuser-0.18.0/README.md similarity index 100% rename from core/patches/fuser-0.18.0/README.md rename to engine/patches/fuser-0.18.0/README.md diff --git a/core/patches/fuser-0.18.0/lifecycle-provenance.json b/engine/patches/fuser-0.18.0/lifecycle-provenance.json similarity index 100% rename from core/patches/fuser-0.18.0/lifecycle-provenance.json rename to engine/patches/fuser-0.18.0/lifecycle-provenance.json diff --git a/core/patches/fuser-0.18.0/provenance.json b/engine/patches/fuser-0.18.0/provenance.json similarity index 100% rename from core/patches/fuser-0.18.0/provenance.json rename to engine/patches/fuser-0.18.0/provenance.json diff --git a/core/patches/fuser-0.18.0/receive-buffer-provenance.json b/engine/patches/fuser-0.18.0/receive-buffer-provenance.json similarity index 100% rename from core/patches/fuser-0.18.0/receive-buffer-provenance.json rename to engine/patches/fuser-0.18.0/receive-buffer-provenance.json diff --git a/core/patches/fuser-0.18.0/receive-buffer.patch b/engine/patches/fuser-0.18.0/receive-buffer.patch similarity index 100% rename from core/patches/fuser-0.18.0/receive-buffer.patch rename to engine/patches/fuser-0.18.0/receive-buffer.patch diff --git a/core/patches/fuser-0.18.0/session-lifecycle.patch b/engine/patches/fuser-0.18.0/session-lifecycle.patch similarity index 100% rename from core/patches/fuser-0.18.0/session-lifecycle.patch rename to engine/patches/fuser-0.18.0/session-lifecycle.patch diff --git a/core/patches/fuser-0.18.0/signed-timestamps.patch b/engine/patches/fuser-0.18.0/signed-timestamps.patch similarity index 100% rename from core/patches/fuser-0.18.0/signed-timestamps.patch rename to engine/patches/fuser-0.18.0/signed-timestamps.patch diff --git a/core/vendor/fuser-0.18.0/.cargo_vcs_info.json b/engine/vendor/fuser-0.18.0/.cargo_vcs_info.json similarity index 100% rename from core/vendor/fuser-0.18.0/.cargo_vcs_info.json rename to engine/vendor/fuser-0.18.0/.cargo_vcs_info.json diff --git a/core/vendor/fuser-0.18.0/.dockerignore b/engine/vendor/fuser-0.18.0/.dockerignore similarity index 100% rename from core/vendor/fuser-0.18.0/.dockerignore rename to engine/vendor/fuser-0.18.0/.dockerignore diff --git a/core/vendor/fuser-0.18.0/.github/workflows/ci.yml b/engine/vendor/fuser-0.18.0/.github/workflows/ci.yml similarity index 100% rename from core/vendor/fuser-0.18.0/.github/workflows/ci.yml rename to engine/vendor/fuser-0.18.0/.github/workflows/ci.yml diff --git a/core/vendor/fuser-0.18.0/.gitignore b/engine/vendor/fuser-0.18.0/.gitignore similarity index 100% rename from core/vendor/fuser-0.18.0/.gitignore rename to engine/vendor/fuser-0.18.0/.gitignore diff --git a/core/vendor/fuser-0.18.0/AGENTS.md b/engine/vendor/fuser-0.18.0/AGENTS.md similarity index 100% rename from core/vendor/fuser-0.18.0/AGENTS.md rename to engine/vendor/fuser-0.18.0/AGENTS.md diff --git a/core/vendor/fuser-0.18.0/CHANGELOG.md b/engine/vendor/fuser-0.18.0/CHANGELOG.md similarity index 100% rename from core/vendor/fuser-0.18.0/CHANGELOG.md rename to engine/vendor/fuser-0.18.0/CHANGELOG.md diff --git a/core/vendor/fuser-0.18.0/CLAUDE.md b/engine/vendor/fuser-0.18.0/CLAUDE.md similarity index 100% rename from core/vendor/fuser-0.18.0/CLAUDE.md rename to engine/vendor/fuser-0.18.0/CLAUDE.md diff --git a/core/vendor/fuser-0.18.0/Cargo.lock b/engine/vendor/fuser-0.18.0/Cargo.lock similarity index 100% rename from core/vendor/fuser-0.18.0/Cargo.lock rename to engine/vendor/fuser-0.18.0/Cargo.lock diff --git a/core/vendor/fuser-0.18.0/Cargo.toml b/engine/vendor/fuser-0.18.0/Cargo.toml similarity index 100% rename from core/vendor/fuser-0.18.0/Cargo.toml rename to engine/vendor/fuser-0.18.0/Cargo.toml diff --git a/core/vendor/fuser-0.18.0/Cargo.toml.orig b/engine/vendor/fuser-0.18.0/Cargo.toml.orig similarity index 100% rename from core/vendor/fuser-0.18.0/Cargo.toml.orig rename to engine/vendor/fuser-0.18.0/Cargo.toml.orig diff --git a/core/vendor/fuser-0.18.0/LICENSE.md b/engine/vendor/fuser-0.18.0/LICENSE.md similarity index 100% rename from core/vendor/fuser-0.18.0/LICENSE.md rename to engine/vendor/fuser-0.18.0/LICENSE.md diff --git a/core/vendor/fuser-0.18.0/Makefile b/engine/vendor/fuser-0.18.0/Makefile similarity index 100% rename from core/vendor/fuser-0.18.0/Makefile rename to engine/vendor/fuser-0.18.0/Makefile diff --git a/core/vendor/fuser-0.18.0/README.md b/engine/vendor/fuser-0.18.0/README.md similarity index 100% rename from core/vendor/fuser-0.18.0/README.md rename to engine/vendor/fuser-0.18.0/README.md diff --git a/core/vendor/fuser-0.18.0/build.rs b/engine/vendor/fuser-0.18.0/build.rs similarity index 100% rename from core/vendor/fuser-0.18.0/build.rs rename to engine/vendor/fuser-0.18.0/build.rs diff --git a/core/vendor/fuser-0.18.0/deny.toml b/engine/vendor/fuser-0.18.0/deny.toml similarity index 100% rename from core/vendor/fuser-0.18.0/deny.toml rename to engine/vendor/fuser-0.18.0/deny.toml diff --git a/core/vendor/fuser-0.18.0/examples/async_hello.rs b/engine/vendor/fuser-0.18.0/examples/async_hello.rs similarity index 100% rename from core/vendor/fuser-0.18.0/examples/async_hello.rs rename to engine/vendor/fuser-0.18.0/examples/async_hello.rs diff --git a/core/vendor/fuser-0.18.0/examples/common/args.rs b/engine/vendor/fuser-0.18.0/examples/common/args.rs similarity index 100% rename from core/vendor/fuser-0.18.0/examples/common/args.rs rename to engine/vendor/fuser-0.18.0/examples/common/args.rs diff --git a/core/vendor/fuser-0.18.0/examples/common/mod.rs b/engine/vendor/fuser-0.18.0/examples/common/mod.rs similarity index 100% rename from core/vendor/fuser-0.18.0/examples/common/mod.rs rename to engine/vendor/fuser-0.18.0/examples/common/mod.rs diff --git a/core/vendor/fuser-0.18.0/examples/hello.rs b/engine/vendor/fuser-0.18.0/examples/hello.rs similarity index 100% rename from core/vendor/fuser-0.18.0/examples/hello.rs rename to engine/vendor/fuser-0.18.0/examples/hello.rs diff --git a/core/vendor/fuser-0.18.0/examples/ioctl.rs b/engine/vendor/fuser-0.18.0/examples/ioctl.rs similarity index 100% rename from core/vendor/fuser-0.18.0/examples/ioctl.rs rename to engine/vendor/fuser-0.18.0/examples/ioctl.rs diff --git a/core/vendor/fuser-0.18.0/examples/notify_inval_entry.rs b/engine/vendor/fuser-0.18.0/examples/notify_inval_entry.rs similarity index 100% rename from core/vendor/fuser-0.18.0/examples/notify_inval_entry.rs rename to engine/vendor/fuser-0.18.0/examples/notify_inval_entry.rs diff --git a/core/vendor/fuser-0.18.0/examples/notify_inval_inode.rs b/engine/vendor/fuser-0.18.0/examples/notify_inval_inode.rs similarity index 100% rename from core/vendor/fuser-0.18.0/examples/notify_inval_inode.rs rename to engine/vendor/fuser-0.18.0/examples/notify_inval_inode.rs diff --git a/core/vendor/fuser-0.18.0/examples/null.rs b/engine/vendor/fuser-0.18.0/examples/null.rs similarity index 100% rename from core/vendor/fuser-0.18.0/examples/null.rs rename to engine/vendor/fuser-0.18.0/examples/null.rs diff --git a/core/vendor/fuser-0.18.0/examples/passthrough.rs b/engine/vendor/fuser-0.18.0/examples/passthrough.rs similarity index 100% rename from core/vendor/fuser-0.18.0/examples/passthrough.rs rename to engine/vendor/fuser-0.18.0/examples/passthrough.rs diff --git a/core/vendor/fuser-0.18.0/examples/passthrough_fork.rs b/engine/vendor/fuser-0.18.0/examples/passthrough_fork.rs similarity index 100% rename from core/vendor/fuser-0.18.0/examples/passthrough_fork.rs rename to engine/vendor/fuser-0.18.0/examples/passthrough_fork.rs diff --git a/core/vendor/fuser-0.18.0/examples/poll.rs b/engine/vendor/fuser-0.18.0/examples/poll.rs similarity index 100% rename from core/vendor/fuser-0.18.0/examples/poll.rs rename to engine/vendor/fuser-0.18.0/examples/poll.rs diff --git a/core/vendor/fuser-0.18.0/examples/poll_client.rs b/engine/vendor/fuser-0.18.0/examples/poll_client.rs similarity index 100% rename from core/vendor/fuser-0.18.0/examples/poll_client.rs rename to engine/vendor/fuser-0.18.0/examples/poll_client.rs diff --git a/core/vendor/fuser-0.18.0/examples/simple.rs b/engine/vendor/fuser-0.18.0/examples/simple.rs similarity index 100% rename from core/vendor/fuser-0.18.0/examples/simple.rs rename to engine/vendor/fuser-0.18.0/examples/simple.rs diff --git a/core/vendor/fuser-0.18.0/mount_tests_libfuse2.Dockerfile b/engine/vendor/fuser-0.18.0/mount_tests_libfuse2.Dockerfile similarity index 100% rename from core/vendor/fuser-0.18.0/mount_tests_libfuse2.Dockerfile rename to engine/vendor/fuser-0.18.0/mount_tests_libfuse2.Dockerfile diff --git a/core/vendor/fuser-0.18.0/mount_tests_libfuse3.Dockerfile b/engine/vendor/fuser-0.18.0/mount_tests_libfuse3.Dockerfile similarity index 100% rename from core/vendor/fuser-0.18.0/mount_tests_libfuse3.Dockerfile rename to engine/vendor/fuser-0.18.0/mount_tests_libfuse3.Dockerfile diff --git a/core/vendor/fuser-0.18.0/pjdfs.Dockerfile b/engine/vendor/fuser-0.18.0/pjdfs.Dockerfile similarity index 100% rename from core/vendor/fuser-0.18.0/pjdfs.Dockerfile rename to engine/vendor/fuser-0.18.0/pjdfs.Dockerfile diff --git a/core/vendor/fuser-0.18.0/pjdfs.sh b/engine/vendor/fuser-0.18.0/pjdfs.sh similarity index 100% rename from core/vendor/fuser-0.18.0/pjdfs.sh rename to engine/vendor/fuser-0.18.0/pjdfs.sh diff --git a/core/vendor/fuser-0.18.0/rust-toolchain b/engine/vendor/fuser-0.18.0/rust-toolchain similarity index 100% rename from core/vendor/fuser-0.18.0/rust-toolchain rename to engine/vendor/fuser-0.18.0/rust-toolchain diff --git a/core/vendor/fuser-0.18.0/rustfmt.toml b/engine/vendor/fuser-0.18.0/rustfmt.toml similarity index 100% rename from core/vendor/fuser-0.18.0/rustfmt.toml rename to engine/vendor/fuser-0.18.0/rustfmt.toml diff --git a/core/vendor/fuser-0.18.0/src/access_flags.rs b/engine/vendor/fuser-0.18.0/src/access_flags.rs similarity index 100% rename from core/vendor/fuser-0.18.0/src/access_flags.rs rename to engine/vendor/fuser-0.18.0/src/access_flags.rs diff --git a/core/vendor/fuser-0.18.0/src/bsd_file_flags.rs b/engine/vendor/fuser-0.18.0/src/bsd_file_flags.rs similarity index 100% rename from core/vendor/fuser-0.18.0/src/bsd_file_flags.rs rename to engine/vendor/fuser-0.18.0/src/bsd_file_flags.rs diff --git a/core/vendor/fuser-0.18.0/src/channel.rs b/engine/vendor/fuser-0.18.0/src/channel.rs similarity index 100% rename from core/vendor/fuser-0.18.0/src/channel.rs rename to engine/vendor/fuser-0.18.0/src/channel.rs diff --git a/core/vendor/fuser-0.18.0/src/dev_fuse.rs b/engine/vendor/fuser-0.18.0/src/dev_fuse.rs similarity index 100% rename from core/vendor/fuser-0.18.0/src/dev_fuse.rs rename to engine/vendor/fuser-0.18.0/src/dev_fuse.rs diff --git a/core/vendor/fuser-0.18.0/src/experimental.rs b/engine/vendor/fuser-0.18.0/src/experimental.rs similarity index 100% rename from core/vendor/fuser-0.18.0/src/experimental.rs rename to engine/vendor/fuser-0.18.0/src/experimental.rs diff --git a/core/vendor/fuser-0.18.0/src/forget_one.rs b/engine/vendor/fuser-0.18.0/src/forget_one.rs similarity index 100% rename from core/vendor/fuser-0.18.0/src/forget_one.rs rename to engine/vendor/fuser-0.18.0/src/forget_one.rs diff --git a/core/vendor/fuser-0.18.0/src/lib.rs b/engine/vendor/fuser-0.18.0/src/lib.rs similarity index 100% rename from core/vendor/fuser-0.18.0/src/lib.rs rename to engine/vendor/fuser-0.18.0/src/lib.rs diff --git a/core/vendor/fuser-0.18.0/src/ll/argument.rs b/engine/vendor/fuser-0.18.0/src/ll/argument.rs similarity index 100% rename from core/vendor/fuser-0.18.0/src/ll/argument.rs rename to engine/vendor/fuser-0.18.0/src/ll/argument.rs diff --git a/core/vendor/fuser-0.18.0/src/ll/flags/copy_file_range_flags.rs b/engine/vendor/fuser-0.18.0/src/ll/flags/copy_file_range_flags.rs similarity index 100% rename from core/vendor/fuser-0.18.0/src/ll/flags/copy_file_range_flags.rs rename to engine/vendor/fuser-0.18.0/src/ll/flags/copy_file_range_flags.rs diff --git a/core/vendor/fuser-0.18.0/src/ll/flags/cuse_init_flags.rs b/engine/vendor/fuser-0.18.0/src/ll/flags/cuse_init_flags.rs similarity index 100% rename from core/vendor/fuser-0.18.0/src/ll/flags/cuse_init_flags.rs rename to engine/vendor/fuser-0.18.0/src/ll/flags/cuse_init_flags.rs diff --git a/core/vendor/fuser-0.18.0/src/ll/flags/fattr_flags.rs b/engine/vendor/fuser-0.18.0/src/ll/flags/fattr_flags.rs similarity index 100% rename from core/vendor/fuser-0.18.0/src/ll/flags/fattr_flags.rs rename to engine/vendor/fuser-0.18.0/src/ll/flags/fattr_flags.rs diff --git a/core/vendor/fuser-0.18.0/src/ll/flags/fopen_flags.rs b/engine/vendor/fuser-0.18.0/src/ll/flags/fopen_flags.rs similarity index 100% rename from core/vendor/fuser-0.18.0/src/ll/flags/fopen_flags.rs rename to engine/vendor/fuser-0.18.0/src/ll/flags/fopen_flags.rs diff --git a/core/vendor/fuser-0.18.0/src/ll/flags/fsync_flags.rs b/engine/vendor/fuser-0.18.0/src/ll/flags/fsync_flags.rs similarity index 100% rename from core/vendor/fuser-0.18.0/src/ll/flags/fsync_flags.rs rename to engine/vendor/fuser-0.18.0/src/ll/flags/fsync_flags.rs diff --git a/core/vendor/fuser-0.18.0/src/ll/flags/getattr_flags.rs b/engine/vendor/fuser-0.18.0/src/ll/flags/getattr_flags.rs similarity index 100% rename from core/vendor/fuser-0.18.0/src/ll/flags/getattr_flags.rs rename to engine/vendor/fuser-0.18.0/src/ll/flags/getattr_flags.rs diff --git a/core/vendor/fuser-0.18.0/src/ll/flags/init_flags.rs b/engine/vendor/fuser-0.18.0/src/ll/flags/init_flags.rs similarity index 100% rename from core/vendor/fuser-0.18.0/src/ll/flags/init_flags.rs rename to engine/vendor/fuser-0.18.0/src/ll/flags/init_flags.rs diff --git a/core/vendor/fuser-0.18.0/src/ll/flags/ioctl_flags.rs b/engine/vendor/fuser-0.18.0/src/ll/flags/ioctl_flags.rs similarity index 100% rename from core/vendor/fuser-0.18.0/src/ll/flags/ioctl_flags.rs rename to engine/vendor/fuser-0.18.0/src/ll/flags/ioctl_flags.rs diff --git a/core/vendor/fuser-0.18.0/src/ll/flags/mod.rs b/engine/vendor/fuser-0.18.0/src/ll/flags/mod.rs similarity index 100% rename from core/vendor/fuser-0.18.0/src/ll/flags/mod.rs rename to engine/vendor/fuser-0.18.0/src/ll/flags/mod.rs diff --git a/core/vendor/fuser-0.18.0/src/ll/flags/poll_flags.rs b/engine/vendor/fuser-0.18.0/src/ll/flags/poll_flags.rs similarity index 100% rename from core/vendor/fuser-0.18.0/src/ll/flags/poll_flags.rs rename to engine/vendor/fuser-0.18.0/src/ll/flags/poll_flags.rs diff --git a/core/vendor/fuser-0.18.0/src/ll/flags/read_flags.rs b/engine/vendor/fuser-0.18.0/src/ll/flags/read_flags.rs similarity index 100% rename from core/vendor/fuser-0.18.0/src/ll/flags/read_flags.rs rename to engine/vendor/fuser-0.18.0/src/ll/flags/read_flags.rs diff --git a/core/vendor/fuser-0.18.0/src/ll/flags/release_flags.rs b/engine/vendor/fuser-0.18.0/src/ll/flags/release_flags.rs similarity index 100% rename from core/vendor/fuser-0.18.0/src/ll/flags/release_flags.rs rename to engine/vendor/fuser-0.18.0/src/ll/flags/release_flags.rs diff --git a/core/vendor/fuser-0.18.0/src/ll/flags/write_flags.rs b/engine/vendor/fuser-0.18.0/src/ll/flags/write_flags.rs similarity index 100% rename from core/vendor/fuser-0.18.0/src/ll/flags/write_flags.rs rename to engine/vendor/fuser-0.18.0/src/ll/flags/write_flags.rs diff --git a/core/vendor/fuser-0.18.0/src/ll/fuse_abi.rs b/engine/vendor/fuser-0.18.0/src/ll/fuse_abi.rs similarity index 100% rename from core/vendor/fuser-0.18.0/src/ll/fuse_abi.rs rename to engine/vendor/fuser-0.18.0/src/ll/fuse_abi.rs diff --git a/core/vendor/fuser-0.18.0/src/ll/ioctl.rs b/engine/vendor/fuser-0.18.0/src/ll/ioctl.rs similarity index 100% rename from core/vendor/fuser-0.18.0/src/ll/ioctl.rs rename to engine/vendor/fuser-0.18.0/src/ll/ioctl.rs diff --git a/core/vendor/fuser-0.18.0/src/ll/ioslice_concat.rs b/engine/vendor/fuser-0.18.0/src/ll/ioslice_concat.rs similarity index 100% rename from core/vendor/fuser-0.18.0/src/ll/ioslice_concat.rs rename to engine/vendor/fuser-0.18.0/src/ll/ioslice_concat.rs diff --git a/core/vendor/fuser-0.18.0/src/ll/mod.rs b/engine/vendor/fuser-0.18.0/src/ll/mod.rs similarity index 100% rename from core/vendor/fuser-0.18.0/src/ll/mod.rs rename to engine/vendor/fuser-0.18.0/src/ll/mod.rs diff --git a/core/vendor/fuser-0.18.0/src/ll/notify.rs b/engine/vendor/fuser-0.18.0/src/ll/notify.rs similarity index 100% rename from core/vendor/fuser-0.18.0/src/ll/notify.rs rename to engine/vendor/fuser-0.18.0/src/ll/notify.rs diff --git a/core/vendor/fuser-0.18.0/src/ll/reply.rs b/engine/vendor/fuser-0.18.0/src/ll/reply.rs similarity index 100% rename from core/vendor/fuser-0.18.0/src/ll/reply.rs rename to engine/vendor/fuser-0.18.0/src/ll/reply.rs diff --git a/core/vendor/fuser-0.18.0/src/ll/request.rs b/engine/vendor/fuser-0.18.0/src/ll/request.rs similarity index 100% rename from core/vendor/fuser-0.18.0/src/ll/request.rs rename to engine/vendor/fuser-0.18.0/src/ll/request.rs diff --git a/core/vendor/fuser-0.18.0/src/mnt/fuse2.rs b/engine/vendor/fuser-0.18.0/src/mnt/fuse2.rs similarity index 100% rename from core/vendor/fuser-0.18.0/src/mnt/fuse2.rs rename to engine/vendor/fuser-0.18.0/src/mnt/fuse2.rs diff --git a/core/vendor/fuser-0.18.0/src/mnt/fuse2_sys.rs b/engine/vendor/fuser-0.18.0/src/mnt/fuse2_sys.rs similarity index 100% rename from core/vendor/fuser-0.18.0/src/mnt/fuse2_sys.rs rename to engine/vendor/fuser-0.18.0/src/mnt/fuse2_sys.rs diff --git a/core/vendor/fuser-0.18.0/src/mnt/fuse3.rs b/engine/vendor/fuser-0.18.0/src/mnt/fuse3.rs similarity index 100% rename from core/vendor/fuser-0.18.0/src/mnt/fuse3.rs rename to engine/vendor/fuser-0.18.0/src/mnt/fuse3.rs diff --git a/core/vendor/fuser-0.18.0/src/mnt/fuse3_sys.rs b/engine/vendor/fuser-0.18.0/src/mnt/fuse3_sys.rs similarity index 100% rename from core/vendor/fuser-0.18.0/src/mnt/fuse3_sys.rs rename to engine/vendor/fuser-0.18.0/src/mnt/fuse3_sys.rs diff --git a/core/vendor/fuser-0.18.0/src/mnt/fuse_pure.rs b/engine/vendor/fuser-0.18.0/src/mnt/fuse_pure.rs similarity index 100% rename from core/vendor/fuser-0.18.0/src/mnt/fuse_pure.rs rename to engine/vendor/fuser-0.18.0/src/mnt/fuse_pure.rs diff --git a/core/vendor/fuser-0.18.0/src/mnt/mod.rs b/engine/vendor/fuser-0.18.0/src/mnt/mod.rs similarity index 100% rename from core/vendor/fuser-0.18.0/src/mnt/mod.rs rename to engine/vendor/fuser-0.18.0/src/mnt/mod.rs diff --git a/core/vendor/fuser-0.18.0/src/mnt/mount_options.rs b/engine/vendor/fuser-0.18.0/src/mnt/mount_options.rs similarity index 100% rename from core/vendor/fuser-0.18.0/src/mnt/mount_options.rs rename to engine/vendor/fuser-0.18.0/src/mnt/mount_options.rs diff --git a/core/vendor/fuser-0.18.0/src/notify.rs b/engine/vendor/fuser-0.18.0/src/notify.rs similarity index 100% rename from core/vendor/fuser-0.18.0/src/notify.rs rename to engine/vendor/fuser-0.18.0/src/notify.rs diff --git a/core/vendor/fuser-0.18.0/src/open_flags.rs b/engine/vendor/fuser-0.18.0/src/open_flags.rs similarity index 100% rename from core/vendor/fuser-0.18.0/src/open_flags.rs rename to engine/vendor/fuser-0.18.0/src/open_flags.rs diff --git a/core/vendor/fuser-0.18.0/src/passthrough.rs b/engine/vendor/fuser-0.18.0/src/passthrough.rs similarity index 100% rename from core/vendor/fuser-0.18.0/src/passthrough.rs rename to engine/vendor/fuser-0.18.0/src/passthrough.rs diff --git a/core/vendor/fuser-0.18.0/src/poll_events.rs b/engine/vendor/fuser-0.18.0/src/poll_events.rs similarity index 100% rename from core/vendor/fuser-0.18.0/src/poll_events.rs rename to engine/vendor/fuser-0.18.0/src/poll_events.rs diff --git a/core/vendor/fuser-0.18.0/src/read_buf.rs b/engine/vendor/fuser-0.18.0/src/read_buf.rs similarity index 100% rename from core/vendor/fuser-0.18.0/src/read_buf.rs rename to engine/vendor/fuser-0.18.0/src/read_buf.rs diff --git a/core/vendor/fuser-0.18.0/src/rename_flags.rs b/engine/vendor/fuser-0.18.0/src/rename_flags.rs similarity index 100% rename from core/vendor/fuser-0.18.0/src/rename_flags.rs rename to engine/vendor/fuser-0.18.0/src/rename_flags.rs diff --git a/core/vendor/fuser-0.18.0/src/reply.rs b/engine/vendor/fuser-0.18.0/src/reply.rs similarity index 100% rename from core/vendor/fuser-0.18.0/src/reply.rs rename to engine/vendor/fuser-0.18.0/src/reply.rs diff --git a/core/vendor/fuser-0.18.0/src/request.rs b/engine/vendor/fuser-0.18.0/src/request.rs similarity index 100% rename from core/vendor/fuser-0.18.0/src/request.rs rename to engine/vendor/fuser-0.18.0/src/request.rs diff --git a/core/vendor/fuser-0.18.0/src/request_param.rs b/engine/vendor/fuser-0.18.0/src/request_param.rs similarity index 100% rename from core/vendor/fuser-0.18.0/src/request_param.rs rename to engine/vendor/fuser-0.18.0/src/request_param.rs diff --git a/core/vendor/fuser-0.18.0/src/session.rs b/engine/vendor/fuser-0.18.0/src/session.rs similarity index 100% rename from core/vendor/fuser-0.18.0/src/session.rs rename to engine/vendor/fuser-0.18.0/src/session.rs diff --git a/core/vendor/fuser-0.18.0/src/session/lifecycle.rs b/engine/vendor/fuser-0.18.0/src/session/lifecycle.rs similarity index 100% rename from core/vendor/fuser-0.18.0/src/session/lifecycle.rs rename to engine/vendor/fuser-0.18.0/src/session/lifecycle.rs diff --git a/core/vendor/fuser-0.18.0/src/time.rs b/engine/vendor/fuser-0.18.0/src/time.rs similarity index 100% rename from core/vendor/fuser-0.18.0/src/time.rs rename to engine/vendor/fuser-0.18.0/src/time.rs diff --git a/core/vendor/fuser-0.18.0/tests/bsd_pjdfs.sh b/engine/vendor/fuser-0.18.0/tests/bsd_pjdfs.sh similarity index 100% rename from core/vendor/fuser-0.18.0/tests/bsd_pjdfs.sh rename to engine/vendor/fuser-0.18.0/tests/bsd_pjdfs.sh diff --git a/core/vendor/fuser-0.18.0/tests/macos_pjdfs.sh b/engine/vendor/fuser-0.18.0/tests/macos_pjdfs.sh similarity index 100% rename from core/vendor/fuser-0.18.0/tests/macos_pjdfs.sh rename to engine/vendor/fuser-0.18.0/tests/macos_pjdfs.sh diff --git a/core/vendor/fuser-0.18.0/tests/test_passthrough.sh b/engine/vendor/fuser-0.18.0/tests/test_passthrough.sh similarity index 100% rename from core/vendor/fuser-0.18.0/tests/test_passthrough.sh rename to engine/vendor/fuser-0.18.0/tests/test_passthrough.sh diff --git a/core/vendor/fuser-0.18.0/xfstests.Dockerfile b/engine/vendor/fuser-0.18.0/xfstests.Dockerfile similarity index 100% rename from core/vendor/fuser-0.18.0/xfstests.Dockerfile rename to engine/vendor/fuser-0.18.0/xfstests.Dockerfile diff --git a/core/vendor/fuser-0.18.0/xfstests.sh b/engine/vendor/fuser-0.18.0/xfstests.sh similarity index 100% rename from core/vendor/fuser-0.18.0/xfstests.sh rename to engine/vendor/fuser-0.18.0/xfstests.sh diff --git a/ruff.toml b/ruff.toml index 72d8b0ed2..d8390ad29 100644 --- a/ruff.toml +++ b/ruff.toml @@ -3,7 +3,7 @@ # the pinned version: # pipx run --spec ruff==0.17.2 ruff format # pipx run --spec ruff==0.17.2 ruff check -# Docs, evidence and core/vendor are outside `include` and stay as recorded. -include = ["core/tools/**/*.py", "tools/**/*.py"] +# Docs, evidence and engine/vendor are outside `include` and stay as recorded. +include = ["tools/**/*.py"] target-version = "py311" # tomllib line-length = 120 diff --git a/core/tools/check_fuser_integrity.py b/tools/check_fuser_integrity.py similarity index 98% rename from core/tools/check_fuser_integrity.py rename to tools/check_fuser_integrity.py index 8be08d70a..ae057a111 100644 --- a/core/tools/check_fuser_integrity.py +++ b/tools/check_fuser_integrity.py @@ -21,8 +21,8 @@ OFFICIAL_GIT = "https://github.com/cberner/fuser.git" APPROVED_REVISIONS: tuple[str, ...] = () -PATCH_PACKAGE = Path("core/vendor/fuser-0.18.0") -PATCH_RECORD = Path("core/patches/fuser-0.18.0") +PATCH_PACKAGE = Path("engine/vendor/fuser-0.18.0") +PATCH_RECORD = Path("engine/patches/fuser-0.18.0") BASE_CHECKSUM = "b82b6597d216503555ead6b358f341ef748869bf5c6fbae6a0cb9dd231baecfd" PATCH_CHECKSUM = "854e35c1cdabc8fbe78d5293c947f66130e1c137e88438f2dfe64bf9c2cc804d" TIME_CHECKSUM = "a333dba1c186c022eb55b950ec8895fb767c63e8ca156150b605d31d6876287d" @@ -33,8 +33,8 @@ BUFFER_PROVENANCE_CHECKSUM = "f3c129457d4eadaf41574c2c1b8da40fb80724e5f42602d3766ab140fdd6d39a" BUFFER_PATCH_CHECKSUM = "7af34aeed231619f4757e40614c13b5f5393aa966bd8545a169f1e9fa746303f" BUFFER_FILES = {"src/read_buf.rs", "src/session.rs", "src/session/lifecycle.rs"} -PATCH_MANIFESTS = {"core/Cargo.toml": "vendor/fuser-0.18.0"} -PATCH_LOCKS = {"core/Cargo.lock", "core/vendor/fuser-0.18.0/Cargo.lock"} +PATCH_MANIFESTS = {"Cargo.toml": "engine/vendor/fuser-0.18.0"} +PATCH_LOCKS = {"Cargo.lock", "engine/vendor/fuser-0.18.0/Cargo.lock"} def is_fuser(name, value): @@ -291,7 +291,7 @@ def repository_errors(root: Path): def main(): parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument("--root", type=Path, default=Path(__file__).resolve().parents[2]) + parser.add_argument("--root", type=Path, default=Path(__file__).resolve().parents[1]) parser.add_argument("--archive", type=Path) parser.add_argument("--package-directory", type=Path) parser.add_argument("--locked-checksum") diff --git a/core/tools/check_product_boundary.py b/tools/check_product_boundary.py similarity index 92% rename from core/tools/check_product_boundary.py rename to tools/check_product_boundary.py index 7118b9030..1a262b9d2 100644 --- a/core/tools/check_product_boundary.py +++ b/tools/check_product_boundary.py @@ -1,4 +1,4 @@ -"""Small source-text guard for core/AGENTS.md; semantic review is still required.""" +"""Small source-text guard for the product layer guides; semantic review is still required.""" import re import sys @@ -154,9 +154,17 @@ def layer_violations(name, dependency, kind): return [] -def crate_directories(core): - """All Rust crate roots; keep layout knowledge in one helper.""" - return sorted(path for path in (core / "crates").glob("*") if path.is_dir()) + [core.parent / "api/binding"] +CRATE_ROOTS = ("core/crates", "engine/crates", "api") + + +def crate_directories(root): + """Every crate root, including unknown crates so the layer map fails closed.""" + return sorted( + path + for relative in CRATE_ROOTS + for path in (root / relative).glob("*") + if path.is_dir() and (relative != "api" or (path / "Cargo.toml").is_file()) + ) def test_path_violations(path, source, packages): @@ -297,13 +305,19 @@ def component_violations(path, source): def crate_name(path): - """The core workspace crate a path belongs to, when it belongs to one.""" + """The product crate a path belongs to, when it belongs to one.""" parts = path.parts for index, part in enumerate(parts): if part == "crates" and index + 1 < len(parts): if parts[index + 1] == "layerfs-api" and index + 2 < len(parts) and parts[index + 2] == "core": return "layerfs-api-core" return parts[index + 1] + for index, part in enumerate(parts): + if part == "api" and index + 1 < len(parts): + if parts[index + 1] == "binding": + return "layerfs-node" + if parts[index + 1] == "layerfs-api": + return "layerfs-api" return None @@ -383,11 +397,11 @@ def overlay_terminology_violations(path, source): return found -def production_files(core, include_sdk=True): +def production_files(root, include_sdk=True): """Known product inputs; tests/examples/tools are deliberately outside this scope.""" files = set() - for package in crate_directories(core): - if not include_sdk and package == core.parent / "api/binding": + for package in crate_directories(root): + if not include_sdk and package == root / "api/binding": continue if not package.is_dir(): continue @@ -395,7 +409,7 @@ def production_files(core, include_sdk=True): files.update(path for path in (package / "sql").rglob("*.sql") if path.is_file()) if not include_sdk: return sorted(files) - api = core.parent / "api" + api = root / "api" for directory in ( api / "agent" / "sdk" / "src", api / "agent" / "cli" / "src", @@ -408,27 +422,27 @@ def production_files(core, include_sdk=True): def main(): # --skip-sdk leaves api/ (binding and JS packages) out of the scan; CI uses it (owner, 2026-10-23). - core = Path(__file__).resolve().parents[1] - files = production_files(core, include_sdk="--skip-sdk" not in sys.argv[1:]) + root = Path(__file__).resolve().parents[1] + files = production_files(root, include_sdk="--skip-sdk" not in sys.argv[1:]) failures = 0 for path in files: for line, reason in violations(path, path.read_text()): - print(f"{path.relative_to(core.parent)}:{line}: {reason}") + print(f"{path.relative_to(root)}:{line}: {reason}") failures += 1 for name in RETIRED_PACKAGES: - if (core / "crates" / name).exists(): + if any((root / relative / name).exists() for relative in CRATE_ROOTS): print(f"crates/{name}: {RETIRED_PACKAGE}") failures += 1 - manifests = {root / "Cargo.toml" for root in crate_directories(core) if (root / "Cargo.toml").is_file()} + manifests = {root / "Cargo.toml" for root in crate_directories(root) if (root / "Cargo.toml").is_file()} packages = {manifest.parent: tomllib.loads(manifest.read_text())["package"]["name"] for manifest in manifests} for manifest in sorted(manifests): for line, reason in dependency_violations(manifest.read_text()): - print(f"{manifest.relative_to(core.parent)}:{line}: {reason}") + print(f"{manifest.relative_to(root)}:{line}: {reason}") failures += 1 for package in packages: for path in sorted((package / "tests").rglob("*.rs")): for line, reason in test_path_violations(path, path.read_text(), packages): - print(f"{path.relative_to(core.parent)}:{line}: {reason}") + print(f"{path.relative_to(root)}:{line}: {reason}") failures += 1 if failures: print(f"FAIL: {failures} product-source boundary violations") diff --git a/core/tools/ci_tests.py b/tools/ci_tests.py similarity index 97% rename from core/tools/ci_tests.py rename to tools/ci_tests.py index 27bc1998f..22f12075a 100644 --- a/core/tools/ci_tests.py +++ b/tools/ci_tests.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 """Test selection for the non-blocking GitHub CI (.github/workflows/). -One place decides which core test binaries run on every push and which wait for +One place decides which product test binaries run on every push and which wait for the nightly run. Nothing here blocks a push or merge. The push job builds only the targets it runs: building, not running, is what its time goes to. @@ -32,8 +32,8 @@ import sys from pathlib import Path -ROOT = Path(__file__).resolve().parents[2] -MANIFEST = ROOT / "core" / "Cargo.toml" +ROOT = Path(__file__).resolve().parents[1] +MANIFEST = ROOT / "Cargo.toml" LINUX_ONLY = '#![cfg(target_os = "linux")]' MOUNT_PACKAGE = "layerfs-daemon" API_MOUNT_TARGETS = {"kernel_mount_routes", "kernel_application", "observed_application", "r5_1_actual_daemon_commit"} diff --git a/tools/cleanup_discover.py b/tools/cleanup_discover.py index 580492e29..64a1abbf9 100644 --- a/tools/cleanup_discover.py +++ b/tools/cleanup_discover.py @@ -21,6 +21,7 @@ def repository_container(container, repo, registered): def cargo_profiles(worktree): """Find real Cargo targets, including the repository's nested Linux targets.""" + # Keep discovering the retired target path for other worktrees awaiting rebase. for root in (worktree / "target", worktree / "core/target"): if not root.is_dir() or root.is_symlink(): continue diff --git a/tools/decode_observations.py b/tools/decode_observations.py index a21104887..7a6945592 100644 --- a/tools/decode_observations.py +++ b/tools/decode_observations.py @@ -9,7 +9,7 @@ This tool reads such a stream (other lines are skipped), groups the records of one call by daemon, scope and call, names every section and value from the -source order in core/crates/layerfs-daemon/src/application/diagnostics/ +source order in engine/crates/layerfs-daemon/src/application/diagnostics/ (diagnostics.rs, schema.rs, kernel.rs, resources.rs), and prints one JSON object per call. With --trace it adds the SDK trace line id whose `scope` matches, so each traced SDK call links to its daemon records. diff --git a/core/tools/phase7_services.py b/tools/phase7_services.py similarity index 99% rename from core/tools/phase7_services.py rename to tools/phase7_services.py index 6dff054f8..e158feb7d 100644 --- a/core/tools/phase7_services.py +++ b/tools/phase7_services.py @@ -15,7 +15,7 @@ import urllib.request from urllib.parse import urlparse -ROOT = Path(__file__).resolve().parents[2] +ROOT = Path(__file__).resolve().parents[1] STATE = ROOT / "target" / "phase7-services" / "settings.json" POSTGRES_IMAGE = "postgres@sha256:639ab7ceb90e13123085b741fb31ef493fba25463002f6da665352e7b534b652" MINIO_IMAGE = "cgr.dev/chainguard/minio@sha256:4692462f35d97d7e82c30371d82f057703c5d9489bcae726010594c812f2d285" diff --git a/tools/preflight.sh b/tools/preflight.sh index 4126dbd19..ba6179385 100755 --- a/tools/preflight.sh +++ b/tools/preflight.sh @@ -14,11 +14,11 @@ # Verify the tree you actually changed, per workspace: # # core (the replacement product): -# cargo +1.85.1 test --manifest-path core/Cargo.toml --locked -# cargo +1.85.1 clippy --manifest-path core/Cargo.toml --locked --all-targets -- -D warnings -# cargo +1.85.1 fmt --manifest-path core/Cargo.toml --all --check -# python3 core/tools/check_product_boundary.py -# python3 -m unittest discover -s core/tools -p 'test_*.py' +# cargo +1.85.1 test --manifest-path Cargo.toml --locked +# cargo +1.85.1 clippy --manifest-path Cargo.toml --locked --all-targets -- -D warnings +# cargo +1.85.1 fmt --manifest-path Cargo.toml --all --check +# python3 tools/check_product_boundary.py +# python3 -m unittest discover -s tools -p 'test_*.py' # # The root crates/ reference workspace was retired by R9c (2026-10-10) and # has no commands at HEAD; it is at local tag reference-v0.1.6-final. diff --git a/tools/production_loc.py b/tools/production_loc.py index 43a566e01..1086aeef2 100755 --- a/tools/production_loc.py +++ b/tools/production_loc.py @@ -2,14 +2,17 @@ """Count first-party production source lines for the per-commit LOC rule. Production code is nonblank, non-comment first-party product implementation: -the replacement product under core/crates/*/src and the reference product under -crates/*/src, plus the runtime SQL that ships with either product under +the product under core/crates/*/src, engine/crates/*/src and api/layerfs-api/src, +and the reference product under crates/*/src, plus shipped runtime SQL under /sql/. Tests, examples, benches, fixtures, benchmark harnesses, development tools, docs, manifests and generated artifacts are excluded. Legacy inline #[cfg(test)] items are removed before counting, because the reference tree keeps tests inside src/. -The JavaScript API is its own scope, `api` (#428): the Node binding's Rust +Rust crates are assigned by name to core, engine or api in both the old and +new layouts. Unknown historical crates remain counted in core. + +The JavaScript API shares the `api` scope (#428): the Node binding's Rust under api/binding/src (layerfs-node) and the src/ JavaScript of each package under api/ (api/agent/sdk is @layerfs/agent, api/agent/cli is @layerfs/cli, api/backend and api/runtime), one crate per package, named by its @@ -30,7 +33,7 @@ the move still count it, and reads 0 after it. TypeScript comments are blanked by the same JavaScript scanner. -Runtime SQL is counted for both scopes: a candidate package that ships schema or +Runtime SQL is counted for every product scope: a candidate package that ships schema or query text under /sql/ contributes it exactly like the reference schema. Per-file reporting uses the same classification as the totals, and prints the physical line count separately so the two measures are never confused. @@ -348,12 +351,39 @@ def counted_lines(path: Path) -> int: return sum(1 for line in text.splitlines() if line.strip()) -SCOPES = ("core", "reference", "api", "dsh") +SCOPES = ("core", "engine", "reference", "api", "dsh") +ENGINE_CRATES = { + "layerfs-bridge", + "layerfs-daemon", + "layerfs-fuse", + "layerfs-overlay", + "layerfs-persistence", + "layerfs-project", + "layerfs-sandbox", + "layerfs-store-service", + "layerfs-workspace", +} + + +def crate_layer(name: str) -> str: + if name == "layerfs-api": + return "api" + if name in ENGINE_CRATES: + return "engine" + # Historical and synthetic crates remain counted rather than disappearing. + return "core" + + +def replacement_packages(root: Path) -> list: + return sorted( + [p for base in (root / "core/crates", root / "engine/crates") for p in base.glob("*") if p.is_dir()] + + ([root / "api/layerfs-api"] if (root / "api/layerfs-api").is_dir() else []) + ) def scope_base(root: Path, scope: str) -> Path: - if scope == "core": - return root / "core" / "crates" + if scope in {"core", "engine"}: + return root if scope == "api": return root if scope == "dsh": @@ -401,6 +431,8 @@ def api_files(root: Path) -> list: def api_crate(root: Path, path: Path) -> str: parts = path.relative_to(root).parts + if "layerfs-api" in parts: + return "layerfs-api" if parts[:2] == ("api", "binding") or parts[:3] == ("sdk", "js", "native"): return "layerfs-node" if parts[0] == "cli": @@ -434,17 +466,11 @@ def crate_of(root: Path, scope: str, path: Path) -> str: if scope == "dsh": return dsh_crate(base, path) parts = path.relative_to(root).parts - return parts[2] if scope == "core" else parts[1] + return parts[2] if scope in {"core", "engine"} else parts[1] -def scope_files(root: Path, scope: str) -> list: - base = scope_base(root, scope) - if not base.is_dir(): - return [] - if scope == "api": - return api_files(root) - if scope == "dsh": - return dsh_files(base) +def rust_files(base: Path) -> list: + """Product Rust/runtime SQL under a crate collection, including old API nesting.""" files = [] for path in sorted(base.rglob("*")): if not path.is_file(): @@ -467,6 +493,24 @@ def scope_files(root: Path, scope: str) -> list: return [path for path in files if path not in excluded] +def scope_files(root: Path, scope: str) -> list: + if scope in {"core", "engine", "api"}: + files = [] + packages = replacement_packages(root) + for base in sorted({package.parent for package in packages}): + names = { + package.name for package in packages if package.parent == base and crate_layer(package.name) == scope + } + files.extend(path for path in rust_files(base) if path.relative_to(base).parts[0] in names) + if scope == "api": + files.extend(api_files(root)) + return sorted(set(files)) + base = scope_base(root, scope) + if not base.is_dir(): + return [] + return dsh_files(base) if scope == "dsh" else rust_files(base) + + def physical_lines(path: Path) -> int: """Every physical line, including comments and blanks; a ceiling measure.""" with path.open(encoding="utf-8") as handle: @@ -523,6 +567,9 @@ def main() -> int: args = parser.parse_args() if args.files: report = per_file(Path(args.root).resolve()) + if args.json: + print(json.dumps(report, indent=2, sort_keys=True)) + return 0 print(f"{'path':<78} {'scope':<9} {'prod':>7} {'physical':>9}") for entry in report["files"]: print(f"{entry['path']:<78} {entry['scope']:<9} {entry['production_loc']:>7} {entry['physical_lines']:>9}") diff --git a/core/tools/sdk_telemetry_report.py b/tools/sdk_telemetry_report.py similarity index 100% rename from core/tools/sdk_telemetry_report.py rename to tools/sdk_telemetry_report.py diff --git a/tools/stage5_component_comparison.py b/tools/stage5_component_comparison.py index 8fb9a5c34..f3a7fdaeb 100755 --- a/tools/stage5_component_comparison.py +++ b/tools/stage5_component_comparison.py @@ -84,7 +84,7 @@ def main(): commit = subprocess.check_output(["git", "rev-parse", "HEAD"], cwd=ROOT, text=True).strip() dirty = subprocess.check_output( - ["git", "status", "--porcelain", "--", "core/crates", "crates"], + ["git", "status", "--porcelain", "--", "core/crates", "engine/crates", "api", "crates"], cwd=ROOT, text=True, ).strip() @@ -105,7 +105,7 @@ def main(): ), ( "candidate", - "core/Cargo.toml", + "Cargo.toml", "layerfs-content", "filesystem_primitives_candidate", ), diff --git a/core/tools/substitution-proof/README.md b/tools/substitution-proof/README.md similarity index 100% rename from core/tools/substitution-proof/README.md rename to tools/substitution-proof/README.md diff --git a/core/tools/substitution-proof/arms/baseline/Cargo.lock b/tools/substitution-proof/arms/baseline/Cargo.lock similarity index 100% rename from core/tools/substitution-proof/arms/baseline/Cargo.lock rename to tools/substitution-proof/arms/baseline/Cargo.lock diff --git a/core/tools/substitution-proof/arms/baseline/Cargo.toml b/tools/substitution-proof/arms/baseline/Cargo.toml similarity index 100% rename from core/tools/substitution-proof/arms/baseline/Cargo.toml rename to tools/substitution-proof/arms/baseline/Cargo.toml diff --git a/core/tools/substitution-proof/arms/c1-only/Cargo.lock b/tools/substitution-proof/arms/c1-only/Cargo.lock similarity index 100% rename from core/tools/substitution-proof/arms/c1-only/Cargo.lock rename to tools/substitution-proof/arms/c1-only/Cargo.lock diff --git a/core/tools/substitution-proof/arms/c1-only/Cargo.toml b/tools/substitution-proof/arms/c1-only/Cargo.toml similarity index 100% rename from core/tools/substitution-proof/arms/c1-only/Cargo.toml rename to tools/substitution-proof/arms/c1-only/Cargo.toml diff --git a/core/tools/substitution-proof/arms/c2-only/Cargo.lock b/tools/substitution-proof/arms/c2-only/Cargo.lock similarity index 100% rename from core/tools/substitution-proof/arms/c2-only/Cargo.lock rename to tools/substitution-proof/arms/c2-only/Cargo.lock diff --git a/core/tools/substitution-proof/arms/c2-only/Cargo.toml b/tools/substitution-proof/arms/c2-only/Cargo.toml similarity index 100% rename from core/tools/substitution-proof/arms/c2-only/Cargo.toml rename to tools/substitution-proof/arms/c2-only/Cargo.toml diff --git a/core/tools/substitution-proof/arms/combined/Cargo.lock b/tools/substitution-proof/arms/combined/Cargo.lock similarity index 100% rename from core/tools/substitution-proof/arms/combined/Cargo.lock rename to tools/substitution-proof/arms/combined/Cargo.lock diff --git a/core/tools/substitution-proof/arms/combined/Cargo.toml b/tools/substitution-proof/arms/combined/Cargo.toml similarity index 100% rename from core/tools/substitution-proof/arms/combined/Cargo.toml rename to tools/substitution-proof/arms/combined/Cargo.toml diff --git a/core/tools/substitution-proof/consumer/core_pipeline.rs b/tools/substitution-proof/consumer/core_pipeline.rs similarity index 100% rename from core/tools/substitution-proof/consumer/core_pipeline.rs rename to tools/substitution-proof/consumer/core_pipeline.rs diff --git a/core/tools/substitution-proof/consumer/cross_revision.rs b/tools/substitution-proof/consumer/cross_revision.rs similarity index 100% rename from core/tools/substitution-proof/consumer/cross_revision.rs rename to tools/substitution-proof/consumer/cross_revision.rs diff --git a/core/tools/substitution-proof/consumer/filesystem_primitives_candidate.rs b/tools/substitution-proof/consumer/filesystem_primitives_candidate.rs similarity index 100% rename from core/tools/substitution-proof/consumer/filesystem_primitives_candidate.rs rename to tools/substitution-proof/consumer/filesystem_primitives_candidate.rs diff --git a/core/tools/substitution-proof/consumer/support/filesystem.rs b/tools/substitution-proof/consumer/support/filesystem.rs similarity index 100% rename from core/tools/substitution-proof/consumer/support/filesystem.rs rename to tools/substitution-proof/consumer/support/filesystem.rs diff --git a/core/tools/substitution-proof/consumer/support/mod.rs b/tools/substitution-proof/consumer/support/mod.rs similarity index 100% rename from core/tools/substitution-proof/consumer/support/mod.rs rename to tools/substitution-proof/consumer/support/mod.rs diff --git a/core/tools/substitution-proof/matrix.json b/tools/substitution-proof/matrix.json similarity index 100% rename from core/tools/substitution-proof/matrix.json rename to tools/substitution-proof/matrix.json diff --git a/core/tools/substitution-proof/run.py b/tools/substitution-proof/run.py similarity index 94% rename from core/tools/substitution-proof/run.py rename to tools/substitution-proof/run.py index 55f5d29d5..eeaeb5cb2 100755 --- a/core/tools/substitution-proof/run.py +++ b/tools/substitution-proof/run.py @@ -36,7 +36,7 @@ from pathlib import Path HERE = Path(__file__).resolve().parent -REPO = HERE.parents[2] +REPO = HERE.parents[1] CRATES = ("layerfs-telemetry", "layerfs-content", "layerfs-storage") ARMS = { "baseline": ("baseline", "baseline"), @@ -60,9 +60,9 @@ [workspace] [dependencies] -layerfs-content = {{ path = "{tree}/crates/layerfs-content" }} -layerfs-storage = {{ path = "{tree}/crates/layerfs-storage" }} -layerfs-telemetry = {{ path = "{tree}/crates/layerfs-telemetry" }} +layerfs-content = {{ path = "{tree}/core/crates/layerfs-content" }} +layerfs-storage = {{ path = "{tree}/core/crates/layerfs-storage" }} +layerfs-telemetry = {{ path = "{tree}/core/crates/layerfs-telemetry" }} rusqlite = {{ version = "=0.40.2", features = ["cache", "hooks", "trace", "limits", "blob"] }} [[test]] @@ -109,14 +109,14 @@ def materialize(root: Path, arm: str, revisions: dict[str, Path]) -> Path: tree = root / arm if tree.exists(): shutil.rmtree(tree) - (tree / "crates").mkdir(parents=True) - shutil.copy2(REPO / "core" / "Cargo.toml", tree / "Cargo.toml") - shutil.copy2(REPO / "core" / "Cargo.lock", tree / "Cargo.lock") + (tree / "core/crates").mkdir(parents=True) + shutil.copy2(REPO / "Cargo.toml", tree / "Cargo.toml") + shutil.copy2(REPO / "Cargo.lock", tree / "Cargo.lock") # telemetry is byte-identical in both revisions; it comes from the repository # so that a mixed arm still has exactly one copy in its graph. for crate, side in zip(CRATES, ("head", *ARMS[arm])): source = (REPO if side == "head" else revisions[side]) / "core" / "crates" / crate - shutil.copytree(source, tree / "crates" / crate, ignore=shutil.ignore_patterns("target", "*.pyc")) + shutil.copytree(source, tree / "core/crates" / crate, ignore=shutil.ignore_patterns("target", "*.pyc")) return tree @@ -158,7 +158,7 @@ def main() -> int: # The materialized crates must be the revision's crates, byte for byte. for crate, side in zip(CRATES[1:], (c1_side, c2_side)): source = (REPO if side == "head" else revisions[side]) / "core" / "crates" / crate - live = tree / "crates" / crate + live = tree / "core/crates" / crate differing = [ str(p.relative_to(source)) for p in source.rglob("*.rs") diff --git a/core/tools/test_check_fuser_integrity.py b/tools/test_check_fuser_integrity.py similarity index 97% rename from core/tools/test_check_fuser_integrity.py rename to tools/test_check_fuser_integrity.py index 3ba015b80..ebd32d085 100644 --- a/core/tools/test_check_fuser_integrity.py +++ b/tools/test_check_fuser_integrity.py @@ -64,7 +64,7 @@ def test_registry_lock_requires_checksum(self): self.assertFalse(lock_errors({"package": [item]})) def test_only_exact_owner_authorized_manifest_patch_is_allowed(self): - path = PATCH_MANIFESTS["core/Cargo.toml"] + path = PATCH_MANIFESTS["Cargo.toml"] doc = {"patch": {"crates-io": {"fuser": {"version": "=0.18.0", "path": path}}}} self.assertFalse(manifest_errors(doc, patch_path=path)) self.assertTrue(manifest_errors(doc)) @@ -83,7 +83,7 @@ def test_patch_lock_requires_owning_context_exact_version_and_no_false_checksum( self.assertTrue(lock_errors({"package": [registry]}, patched=True)) def test_authorized_package_rejects_unrelated_edits_inventory_changes_and_redirects(self): - repository = Path(__file__).resolve().parents[2] + repository = Path(__file__).resolve().parents[1] with TemporaryDirectory() as directory: root = Path(directory) shutil.copytree(repository / PATCH_RECORD, root / PATCH_RECORD) @@ -115,7 +115,7 @@ def test_authorized_package_rejects_unrelated_edits_inventory_changes_and_redire self.assertTrue(patched_package_errors(root)) def test_lifecycle_provenance_and_diff_are_both_required_and_exact(self): - repository = Path(__file__).resolve().parents[2] + repository = Path(__file__).resolve().parents[1] with TemporaryDirectory() as directory: root = Path(directory) shutil.copytree(repository / PATCH_RECORD, root / PATCH_RECORD) diff --git a/core/tools/test_check_product_boundary.py b/tools/test_check_product_boundary.py similarity index 90% rename from core/tools/test_check_product_boundary.py rename to tools/test_check_product_boundary.py index 8ecf49c91..00b86800e 100644 --- a/core/tools/test_check_product_boundary.py +++ b/tools/test_check_product_boundary.py @@ -5,6 +5,7 @@ from check_product_boundary import ( RETIRED_PACKAGES, + crate_directories, dependency_violations, production_files, test_path_violations, @@ -15,7 +16,7 @@ class ProductBoundaryTests(unittest.TestCase): def test_native_fuse_owns_requests_without_reverse_daemon_dependency(self): - path = Path("core/crates/layerfs-fuse/src/ports.rs") + path = Path("engine/crates/layerfs-fuse/src/ports.rs") for source in [ "use layerfs_workspace::SourceView;", "use layerfs_overlay::NativeMount;", @@ -29,7 +30,7 @@ def test_native_fuse_owns_requests_without_reverse_daemon_dependency(self): ]: self.assertTrue(violations(path, source)) self.assertTrue(unsafe_violations(path, "unsafe fn syscall() {}")) - root = Path("core/crates/layerfs-fuse/src/lib.rs") + root = Path("engine/crates/layerfs-fuse/src/lib.rs") self.assertFalse(unsafe_violations(root, "#![forbid(unsafe_code)]")) self.assertTrue(unsafe_violations(root, "mod mount;")) prefix = '[package]\nname="layerfs-fuse"\n[dependencies]\n' @@ -41,7 +42,7 @@ def test_native_fuse_owns_requests_without_reverse_daemon_dependency(self): ) def test_overlay_terminology_distinguishes_records_from_temporary_buffers(self): - path = Path("core/crates/layerfs-overlay/src/contract/types.rs") + path = Path("engine/crates/layerfs-overlay/src/contract/types.rs") for source in [ "pub struct Dentry {}", "pub struct ScratchRecord {}", @@ -51,14 +52,14 @@ def test_overlay_terminology_distinguishes_records_from_temporary_buffers(self): self.assertTrue(violations(path, source)) self.assertFalse(violations(path, "pub struct DirectoryEntry {}\npub struct OperationRecord {}")) self.assertFalse(violations(path, "fn encode() { let scratch = Vec::new(); } // temporary buffer")) - sql = Path("core/crates/layerfs-overlay/sql/schema.sql") + sql = Path("engine/crates/layerfs-overlay/sql/schema.sql") self.assertTrue(violations(sql, "CREATE TABLE scratch (value BLOB);")) self.assertFalse(violations(sql, "CREATE TABLE operation_record (value BLOB);")) - bridge = Path("core/crates/layerfs-bridge/src/native/channel.rs") + bridge = Path("engine/crates/layerfs-bridge/src/native/channel.rs") self.assertFalse(violations(bridge, "pub struct ScratchBuffer;")) def test_daemon_store_is_provider_independent(self): - path = Path("core/crates/layerfs-daemon/src/store/open.rs") + path = Path("engine/crates/layerfs-daemon/src/store/open.rs") for source in ["use layerfs_storage::Storage;", "use layerfs_history::HistoryCatalog;"]: self.assertFalse(violations(path, source)) for source in [ @@ -68,11 +69,11 @@ def test_daemon_store_is_provider_independent(self): "use std::path::{Path, PathBuf};", ]: self.assertTrue(violations(path, source)) - bootstrap = Path("core/crates/layerfs-daemon/src/bootstrap.rs") + bootstrap = Path("engine/crates/layerfs-daemon/src/bootstrap.rs") self.assertFalse(violations(bootstrap, "use layerfs_persistence::Handles;")) def test_persistence_seal_ffi_is_limited_to_the_authorized_module(self): - base = Path("core/crates/layerfs-persistence/src") + base = Path("engine/crates/layerfs-persistence/src") ffi = "fn seal() { unsafe { file_control(); } }" self.assertFalse(unsafe_violations(base / "backend/sqlite/file_control.rs", ffi)) for sibling in ["backend/sqlite/seal.rs", "store/seal.rs", "backend/sqlite/connection.rs"]: @@ -112,18 +113,18 @@ def test_retired_packages_cannot_return(self): self.assertTrue(dependency_violations(f'[package]\nname="{name}"\n'), name) def test_sdk_source_edges_and_unsafe_boundary(self): - path = Path("core/crates/layerfs-api/src/project/init.rs") + path = Path("api/layerfs-api/src/project/init.rs") self.assertFalse(violations(path, "use layerfs_persistence::Handles;")) self.assertTrue(violations(path, "use layerfs_server::Server;")) self.assertTrue(unsafe_violations(path, "unsafe fn extend_lifetime() {}")) - root = Path("core/crates/layerfs-api/src/lib.rs") + root = Path("api/layerfs-api/src/lib.rs") self.assertTrue(unsafe_violations(root, "mod init;")) self.assertFalse(unsafe_violations(root, "#![forbid(unsafe_code)]\nmod init;")) def test_sandbox_active_edges_and_unsafe_boundary(self): - path = Path("core/crates/layerfs-sandbox/src/backend/docker/http.rs") + path = Path("engine/crates/layerfs-sandbox/src/backend/docker/http.rs") self.assertTrue(unsafe_violations(path, "unsafe fn signal_pid() {}")) - self.assertFalse(unsafe_violations(Path("core/crates/layerfs-sandbox/src/lib.rs"), "#![forbid(unsafe_code)]")) + self.assertFalse(unsafe_violations(Path("engine/crates/layerfs-sandbox/src/lib.rs"), "#![forbid(unsafe_code)]")) prefix = '[package]\nname="layerfs-sandbox"\n[dependencies]\n' for dependency in ( "layerfs-api-core", @@ -155,7 +156,7 @@ def test_sdk_dependency_edges(self): def test_daemon_direct_store_and_control_edges_without_host_runtime(self): prefix = '[package]\nname="layerfs-daemon"\n[dependencies]\n' - path = Path("core/crates/layerfs-daemon/src/bootstrap.rs") + path = Path("engine/crates/layerfs-daemon/src/bootstrap.rs") for dependency in ( "layerfs-bridge", "layerfs-content", @@ -171,7 +172,7 @@ def test_daemon_direct_store_and_control_edges_without_host_runtime(self): self.assertTrue(violations(path, "use layerfs_api::Runtime;")) sdk = '[package]\nname="layerfs-api"\n[dependencies]\n' self.assertTrue(dependency_violations(sdk + 'layerfs-daemon={path="../../layerfs-daemon"}')) - self.assertTrue(violations(Path("core/crates/layerfs-api/src/project/init.rs"), "use layerfs_daemon::Owner;")) + self.assertTrue(violations(Path("api/layerfs-api/src/project/init.rs"), "use layerfs_daemon::Owner;")) def test_store_service_engine_edges(self): prefix = '[package]\nname="layerfs-store-service"\n[dependencies]\n' @@ -185,7 +186,7 @@ def test_store_service_engine_edges(self): self.assertTrue( violations(Path("core/crates/layerfs-history/src/lib.rs"), "use layerfs_store_service::history::MAIN;") ) - root = Path("core/crates/layerfs-store-service/src/lib.rs") + root = Path("engine/crates/layerfs-store-service/src/lib.rs") self.assertTrue(unsafe_violations(root, "pub mod store;")) self.assertFalse(unsafe_violations(root, "#![forbid(unsafe_code)]\npub mod store;")) self.assertFalse( @@ -199,9 +200,9 @@ def test_workspace_composition_edges_preserve_domain_and_reverse_boundaries(self source = f'[package]\nname="{package}"\n[dependencies]\nlayerfs-workspace={{path="../layerfs-workspace"}}\n' self.assertEqual(bool(dependency_violations(source)), package == "layerfs-api") path = ( - Path("core/crates/layerfs-api/src/project/init.rs") + Path("api/layerfs-api/src/project/init.rs") if package == "layerfs-api" - else Path("core/crates/layerfs-daemon/src/commands.rs") + else Path("engine/crates/layerfs-daemon/src/commands.rs") ) self.assertEqual(bool(violations(path, "use layerfs_workspace::Workspace;")), package == "layerfs-api") self.assertTrue(violations(path, "use layerfs_server::Server;")) @@ -265,12 +266,12 @@ def test_domain_source_component_names(self): self.assertTrue(violations(path, "use layerfs_s3::S3Objects;")) self.assertTrue(violations(path, "// layerfs-metadata owns this")) self.assertTrue(violations(path, "use layerfs_workspace::Workspace;")) - path = Path("core/crates/layerfs-persistence/src/implementation.rs") + path = Path("engine/crates/layerfs-persistence/src/implementation.rs") self.assertFalse(violations(path, "use layerfs_storage::port::MetadataStore;")) self.assertTrue(violations(path, "use layerfs_s3::S3Objects;")) def test_project_store_composition_uses_approved_engine_edges(self): - path = Path("core/crates/layerfs-project/src/store/init.rs") + path = Path("engine/crates/layerfs-project/src/store/init.rs") for dependency in ("layerfs-persistence", "layerfs-bridge"): self.assertFalse(violations(path, f"use {dependency.replace('-', '_')}::PublicType;")) self.assertFalse( @@ -365,7 +366,7 @@ def test_unsafe_boundary(self): def test_shipped_sql_and_external_tests_scope(self): with TemporaryDirectory() as directory: - core = Path(directory) + core = Path(directory) / "core" names = ( "src/lib.rs", "src/sql/query.sql", @@ -380,22 +381,42 @@ def test_shipped_sql_and_external_tests_scope(self): path.parent.mkdir(parents=True, exist_ok=True) path.write_text("") self.assertEqual( - [str(p.relative_to(core / "crates" / "store")) for p in production_files(core)], + [str(p.relative_to(core / "crates" / "store")) for p in production_files(core.parent)], ["sql/schema.sql", "src/lib.rs", "src/sql/query.sql"], ) def test_flat_api_product_scope(self): with TemporaryDirectory() as directory: - core = Path(directory) + root = Path(directory) + package = root / "api/layerfs-api" for name in ("src/lib.rs", "src/fs/read.rs", "tests/route.rs", "examples/demo.rs"): - path = core / "crates/layerfs-api" / name + path = package / name path.parent.mkdir(parents=True, exist_ok=True) path.write_text("") + (package / "Cargo.toml").write_text('[package]\nname="layerfs-api"\n') self.assertEqual( - [str(p.relative_to(core / "crates/layerfs-api")) for p in production_files(core)], + [str(p.relative_to(package)) for p in production_files(root)], ["src/fs/read.rs", "src/lib.rs"], ) + def test_crate_discovery_covers_all_layers_and_unknown_packages(self): + with TemporaryDirectory() as directory: + root = Path(directory) + expected = [] + for relative, name in ( + ("core/crates/layerfs-content", "layerfs-content"), + ("engine/crates/layerfs-project", "layerfs-project"), + ("api/binding", "layerfs-node"), + ("api/layerfs-new", "layerfs-new"), + ): + package = root / relative + package.mkdir(parents=True) + manifest = f'[package]\nname="{name}"\n' + (package / "Cargo.toml").write_text(manifest) + expected.append(package) + self.assertEqual(bool(dependency_violations(manifest)), name == "layerfs-new") + self.assertEqual(crate_directories(root), sorted(expected)) + def test_skip_sdk_leaves_only_the_sdk_out(self): with TemporaryDirectory() as directory: root = Path(directory) @@ -407,11 +428,12 @@ def test_skip_sdk_leaves_only_the_sdk_out(self): ): path.parent.mkdir(parents=True, exist_ok=True) path.write_text("") - everything = [str(p.relative_to(root)) for p in production_files(core)] + (root / "api/binding/Cargo.toml").write_text('[package]\nname="layerfs-node"\n') + everything = [str(p.relative_to(root)) for p in production_files(core.parent)] self.assertIn("api/binding/src/lib.rs", everything) self.assertIn("api/agent/sdk/src/index.js", everything) self.assertEqual( - [str(p.relative_to(root)) for p in production_files(core, include_sdk=False)], + [str(p.relative_to(root)) for p in production_files(core.parent, include_sdk=False)], ["core/crates/store/src/lib.rs"], ) diff --git a/core/tools/test_ci_tests.py b/tools/test_ci_tests.py similarity index 94% rename from core/tools/test_ci_tests.py rename to tools/test_ci_tests.py index 3f3d3f398..1c8476a10 100644 --- a/core/tools/test_ci_tests.py +++ b/tools/test_ci_tests.py @@ -72,13 +72,13 @@ def test_binding_tests_stay_out_of_the_ci_lanes(self): self.assertEqual(list(ci_tests.test_targets(meta)), []) def test_keeps_only_mount_test_binaries(self): - meta = {"packages": [{"name": "layerfs-daemon", "manifest_path": "/w/core/crates/layerfs-daemon/Cargo.toml"}]} + meta = {"packages": [{"name": "layerfs-daemon", "manifest_path": "/w/engine/crates/layerfs-daemon/Cargo.toml"}]} def artifact(name, kind, exe): return json.dumps( { "reason": "compiler-artifact", - "manifest_path": "/w/core/crates/layerfs-daemon/Cargo.toml", + "manifest_path": "/w/engine/crates/layerfs-daemon/Cargo.toml", "target": {"name": name, "kind": [kind]}, "executable": exe, } @@ -91,7 +91,7 @@ def artifact(name, kind, exe): artifact("layerfs-daemon", "bin", "/t/layerfs-daemon"), ] found = list(ci_tests.executables(lines, [("layerfs-daemon", "mounted_commit")], meta)) - self.assertEqual(found, [(Path("/w/core/crates/layerfs-daemon"), "/t/mounted_commit-1")]) + self.assertEqual(found, [(Path("/w/engine/crates/layerfs-daemon"), "/t/mounted_commit-1")]) if __name__ == "__main__": diff --git a/tools/test_cleanup.py b/tools/test_cleanup.py index 0ce61e7da..6771dbf5e 100644 --- a/tools/test_cleanup.py +++ b/tools/test_cleanup.py @@ -339,7 +339,7 @@ def test_container_using_pinned_volume_cannot_be_retired(self): def test_caches_discovery_keeps_helpers_and_active_profile(self): tree = self.root / "linked" - target = tree / "core/target/linux" + target = tree / "target/linux" profile = target / "debug" (profile / "deps").mkdir(parents=True) (target / ".rustc_info.json").write_text("{}") @@ -576,7 +576,7 @@ def test_explicit_cache_discovery_includes_primary_and_limits_scope(self): other = self.root / "linked" self.git("worktree", "add", "--detach", str(other), "HEAD") for tree in (self.repo, other): - target = tree / "core/target" + target = tree / "target" (target / "debug/deps").mkdir(parents=True) (target / ".rustc_info.json").write_text("{}") registered = {str(p): {} for p in (self.repo, other)} @@ -590,9 +590,9 @@ def test_explicit_cache_discovery_includes_primary_and_limits_scope(self): caches_only=True, cache_worktrees=[str(self.repo)], ) - self.assertEqual([a["path"] for a in scope["actions"]], [str(self.repo / "core/target/debug")]) + self.assertEqual([a["path"] for a in scope["actions"]], [str(self.repo / "target/debug")]) default, _ = discover(self.repo, {}, registered, [], [], "user authorized caches", caches_only=True) - self.assertEqual([a["path"] for a in default["actions"]], [str(other / "core/target/debug")]) + self.assertEqual([a["path"] for a in default["actions"]], [str(other / "target/debug")]) def test_archive_across_hash_batches_preserves_every_file(self): source = self.root / "many-files" diff --git a/core/tools/test_phase7_services.py b/tools/test_phase7_services.py similarity index 100% rename from core/tools/test_phase7_services.py rename to tools/test_phase7_services.py diff --git a/tools/test_production_loc.py b/tools/test_production_loc.py index 45ec774f6..0d5e3b6d5 100644 --- a/tools/test_production_loc.py +++ b/tools/test_production_loc.py @@ -22,15 +22,31 @@ def setUp(self): def tearDown(self): self._temporary.cleanup() + def test_layer_classification_survives_relocation(self): + import shutil + + for name in ("layerfs-content", "layerfs-project", "layerfs-api"): + write(self.root, f"core/crates/{name}/src/lib.rs", "pub fn value() {}\n") + write(self.root, f"core/crates/{name}/sql/schema.sql", "CREATE TABLE value(id INTEGER);\n") + before = production_loc.scan(self.root) + (self.root / "engine/crates").mkdir(parents=True) + (self.root / "api").mkdir() + shutil.move(self.root / "core/crates/layerfs-project", self.root / "engine/crates/layerfs-project") + shutil.move(self.root / "core/crates/layerfs-api", self.root / "api/layerfs-api") + after = production_loc.scan(self.root) + self.assertEqual(before, after) + for layer, name in (("core", "layerfs-content"), ("engine", "layerfs-project"), ("api", "layerfs-api")): + self.assertEqual(after["scopes"][layer]["crates"], {name: 2}) + def test_nested_api_members_count_only_product_source(self): for name in ("core/src/lib.rs", "sdk/src/client.rs", "sdk/tests/route.rs", "mcp/src/lib.rs", "cli/src/main.rs"): write(self.root, f"core/crates/layerfs-api/{name}", "pub fn value() {}\n") - files = production_loc.scope_files(self.root, "core") + files = production_loc.scope_files(self.root, "api") self.assertEqual( [str(path.relative_to(self.root / "core/crates/layerfs-api")) for path in files], ["core/src/lib.rs", "sdk/src/client.rs"], ) - self.assertEqual(production_loc.scan(self.root)["scopes"]["core"]["lines"], 2) + self.assertEqual(production_loc.scan(self.root)["scopes"]["api"]["lines"], 2) def test_api_counts_the_binding_and_each_package_by_its_name(self): write(self.root, "api/package.json", '{"name": "layerfs-js"}\n') diff --git a/core/tools/test_sdk_telemetry_report.py b/tools/test_sdk_telemetry_report.py similarity index 100% rename from core/tools/test_sdk_telemetry_report.py rename to tools/test_sdk_telemetry_report.py diff --git a/tools/test_worktree.py b/tools/test_worktree.py index 5c9b8ad05..df5d12258 100644 --- a/tools/test_worktree.py +++ b/tools/test_worktree.py @@ -28,7 +28,9 @@ def setUp(self): self.repo.mkdir() for folder in ( "core/crates/example/src", - "core/vendor", + "engine/vendor", + "engine/crates/example/src", + "api/layerfs-api/src", ".cargo", "api/agent/sdk/src", "api/agent/sdk/test", @@ -37,7 +39,7 @@ def setUp(self): "api/binding/src", ): (self.repo / folder).mkdir(parents=True) - for name in ("core/Cargo.toml", "core/Cargo.lock", ".cargo/config.toml", "api/package.json"): + for name in ("Cargo.toml", "Cargo.lock", ".cargo/config.toml", "api/package.json"): (self.repo / name).write_text("{}\n") (self.repo / "api/agent/sdk/src/index.js").write_text("export const value = 1;\n") (self.repo / "api/agent/sdk/package.json").write_text( @@ -70,6 +72,20 @@ def setUp(self): self.path = self.root / "state" / resources.identity(self.repo) / "resources.json" self.record = resources.load(self.path) + def test_build_identity_covers_each_product_layer(self): + before = resources.inputs(self.record) + for relative in ( + "core/crates/example/src/lib.rs", + "engine/crates/example/src/lib.rs", + "api/layerfs-api/src/lib.rs", + ): + path = self.repo / relative + path.write_text("pub fn layer() {}\n") + after = resources.inputs(self.record) + self.assertIn(relative, after["files"]) + self.assertNotEqual(before["sha256"], after["sha256"]) + before = after + def test_checkout_path_controls_identity_not_basename(self): self.assertNotEqual(resources.identity(self.root / "a/checkout"), resources.identity(self.root / "b/checkout")) self.assertEqual(resources.identity(self.repo), resources.identity(self.repo / ".")) @@ -86,10 +102,10 @@ def test_linux_mounts_do_not_use_host_target_or_shared_home(self): with patch.object(resources, "volume"), patch.dict(os.environ, {}, clear=True): command = resources.docker_build(self.record, ["cargo", "+1.85.1", "build"]) self.assertIn("type=bind,src=" + str(self.repo) + ",dst=/work,readonly", command) - self.assertIn("CARGO_TARGET_DIR=/work/core/target", command) + self.assertIn("CARGO_TARGET_DIR=/work/target", command) self.assertIn("CARGO_HOME=/cargo-home", command) self.assertIn( - "type=volume,src=" + self.record["linux_target_volume"] + ",dst=/work/core/target,volume-nocopy", command + "type=volume,src=" + self.record["linux_target_volume"] + ",dst=/work/target,volume-nocopy", command ) self.assertIn("sha256:build", command) @@ -131,7 +147,7 @@ def test_cargo_scope_and_frozen_harness_guards(self): def test_source_identity_includes_new_source_but_excludes_target(self): before = resources.inputs(self.record) - target = self.repo / "core/target" + target = self.repo / "target" target.mkdir() (target / "generated").write_text("cache") self.assertEqual(before, resources.inputs(self.record)) @@ -144,7 +160,7 @@ def test_source_directory_symlink_refused(self): resources.inputs(self.record) def build_bundle(self, mutate=False): - target = self.repo / "core/target/debug" + target = self.repo / "target/debug" target.mkdir(parents=True) (target / "layerfs-daemon").write_bytes(b"daemon") (target / "layerfs-daemon").chmod(0o755) diff --git a/tools/worktree_build.py b/tools/worktree_build.py index 51677f0bc..9a82672fb 100644 --- a/tools/worktree_build.py +++ b/tools/worktree_build.py @@ -34,7 +34,7 @@ def prepare(args): home.mkdir(mode=0o700, exist_ok=True) if args.dependency_seed: copy_dependencies(args.dependency_seed, home) - command = ["cargo", "+" + TOOLCHAIN, "fetch", "--manifest-path", "core/Cargo.toml", "--locked"] + command = ["cargo", "+" + TOOLCHAIN, "fetch", "--manifest-path", "Cargo.toml", "--locked"] execute(command, record["worktree"], environment(record, "macos"), log=receipt / "output.log") else: for key in ("linux_cargo_volume", "linux_target_volume"): @@ -55,7 +55,7 @@ def prepare(args): execute(command, record["worktree"], log=receipt / "seed.log") command = docker_build( record, - ["cargo", "+" + TOOLCHAIN, "fetch", "--manifest-path", "core/Cargo.toml", "--locked"], + ["cargo", "+" + TOOLCHAIN, "fetch", "--manifest-path", "Cargo.toml", "--locked"], network="default", ) execute(command, record["worktree"], log=receipt / "output.log") @@ -87,7 +87,7 @@ def cargo_arguments(arguments): "+" + TOOLCHAIN, arguments[0], "--manifest-path", - "core/Cargo.toml", + "Cargo.toml", "--locked", "--offline", *arguments[1:], @@ -212,7 +212,7 @@ def build(args): "+" + TOOLCHAIN, "build", "--manifest-path", - "core/Cargo.toml", + "Cargo.toml", "--locked", "--offline", "-p", @@ -229,8 +229,8 @@ def build(args): closed_volumes([record["linux_cargo_volume"], record["linux_target_volume"]]) execute(docker_build(record, command), record["worktree"], log=receipt / "output.log") script = ( - 'set -eu; cp "/work/core/target/$1/layerfs-daemon" /export/layerfs-daemon; ' - 'cp "/work/core/target/$1/liblayerfs_node.so" /export/layerfs.node; ' + 'set -eu; cp "/work/target/$1/layerfs-daemon" /export/layerfs-daemon; ' + 'cp "/work/target/$1/liblayerfs_node.so" /export/layerfs.node; ' 'chown "$2:$3" /export/layerfs-daemon /export/layerfs.node' ) export = docker_build( @@ -280,7 +280,7 @@ def seed(args): raise Refused("Seed source and destination must be different worktrees") if record["images"] != source["images"]: raise Refused("Seed images differ") - for relative in ("core/Cargo.lock", ".cargo/config.toml"): + for relative in ("Cargo.lock", ".cargo/config.toml"): if digest(Path(record["worktree"]) / relative) != digest(Path(source["worktree"]) / relative): raise Refused("Seed lockfile or build configuration differs") with lease(record, args.platform), lease(source, args.platform): @@ -290,8 +290,8 @@ def seed(args): volume(owner, "linux_target_volume") closed_volumes([record["linux_target_volume"], source["linux_target_volume"]]) script = ( - 'set -eu; test ! -e "/work/core/target/$1"; cp -a "/seed/$1" "/work/core/target/$1"; ' - 'for f in .rustc_info.json CACHEDIR.TAG; do if [ -f "/seed/$f" ]; then cp -a "/seed/$f" /work/core/target/; fi; done' + 'set -eu; test ! -e "/work/target/$1"; cp -a "/seed/$1" "/work/target/$1"; ' + 'for f in .rustc_info.json CACHEDIR.TAG; do if [ -f "/seed/$f" ]; then cp -a "/seed/$f" /work/target/; fi; done' ) command = docker_build( record, diff --git a/tools/worktree_resources.py b/tools/worktree_resources.py index 6e38e5f25..3f53ee5a9 100644 --- a/tools/worktree_resources.py +++ b/tools/worktree_resources.py @@ -62,8 +62,8 @@ def register(args): source = Path(args.worktree).resolve() if Path(git(source, "rev-parse", "--show-toplevel").decode().strip()).resolve() != source: raise Refused("Select a Git checkout root") - if not (source / "core/Cargo.toml").is_file(): - raise Refused("Worktree has no active core manifest") + if not (source / "Cargo.toml").is_file(): + raise Refused("Worktree has no active workspace manifest") state = Path(args.root).expanduser().resolve() / identity(source) if overlaps(state, source): raise Refused("Resource state must be outside the worktree") @@ -75,7 +75,7 @@ def register(args): "worktree": str(source), "state": str(state), "toolchain": TOOLCHAIN, - "macos_target": str(source / "core/target"), + "macos_target": str(source / "target"), "macos_cargo_home": str(state / "cargo-home-macos"), "linux_target_volume": "lfs-dev-" + identity(source) + "-target", "linux_cargo_volume": "lfs-dev-" + identity(source) + "-cargo", @@ -151,7 +151,7 @@ def environment(record, platform): if os.uname().sysname != "Darwin": raise Refused("macos builds require a macOS host") return {**os.environ, "CARGO_HOME": record["macos_cargo_home"], "CARGO_TARGET_DIR": record["macos_target"]} - return {"CARGO_HOME": "/cargo-home", "CARGO_TARGET_DIR": "/work/core/target"} + return {"CARGO_HOME": "/cargo-home", "CARGO_TARGET_DIR": "/work/target"} def docker_build(record, command, extra=(), network="none"): @@ -172,7 +172,7 @@ def docker_build(record, command, extra=(), network="none"): "--mount", f"type=bind,src={record['worktree']},dst=/work,readonly", "--mount", - f"type=volume,src={record['linux_target_volume']},dst=/work/core/target,volume-nocopy", + f"type=volume,src={record['linux_target_volume']},dst=/work/target,volume-nocopy", "--mount", f"type=volume,src={record['linux_cargo_volume']},dst=/cargo-home,volume-nocopy", *[v for k, value in env.items() for v in ("-e", k + "=" + value)], @@ -224,10 +224,12 @@ def inputs(record): root = Path(record["worktree"]) selected = [ ".cargo", - "core/Cargo.toml", - "core/Cargo.lock", + "Cargo.toml", + "Cargo.lock", "core/crates", - "core/vendor", + "engine/vendor", + "engine/crates", + "api/layerfs-api", "api/agent/sdk", "api/backend", "api/runtime", From ef4c26b02ba111c2abe2e8d228c156e1f3b6ddc4 Mon Sep 17 00:00:00 2001 From: YifanXu1999 Date: Tue, 27 Oct 2026 03:01:57 +0800 Subject: [PATCH 06/10] chore(ci): record Linux writer admission in the slow lane The migration's full Linux functional run measured the existing layerfs-persistence::writer_admission target at 9.74 seconds. Record that observation in SLOW as the repository rule requires; keep this selection change separate from the path relocation. This is test scheduling, not a performance qualification or product change. Checks: six CI-selection/executable self-tests under a 120-second ceiling; pinned Ruff formatting and whitespace. No Rust product or test body changes, so the completed relocation's Rust/runtime proofs remain applicable. No tests deleted or moved. Production LOC: 102162 -> 102162 (delta +0) Scope: all first-party product implementation, including shipped SQL and JavaScript. before: api 7281, core 38241, engine 56640. after: api 7281, core 38241, engine 56640. Method: tools/production_loc.py --json; exact parent and staged trees; inline tests/comments excluded; shipped SQL and JS included. Counter SHA256: 2903e1aed42f0eebb022b82b5fc2220278ccb870bbc06389adc79c4d340bad59. reference absent (retired R9c; last counted 65,417 at tree 498dd1917812). --- tools/ci_tests.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/ci_tests.py b/tools/ci_tests.py index 22f12075a..6ba4690a9 100644 --- a/tools/ci_tests.py +++ b/tools/ci_tests.py @@ -44,6 +44,8 @@ ("layerfs-node", "native_admission"): 60.52, # Linux SDK mount proof after the ownership move, 2026-10-27. ("layerfs-api", "observed_application"): 6.30, + # Linux functional run at the relocated tree, 2026-10-27. + ("layerfs-persistence", "writer_admission"): 9.74, ("layerfs-api", "scale_lineage_cap"): 24.3, ("layerfs-api", "sdk_merge_scale"): 23.8, ("layerfs-daemon", "complete_installed_roots"): 9.0, From 853abcbe2bc0eadedf0d9d73ce39b32998e33a35 Mon Sep 17 00:00:00 2001 From: YifanXu1999 Date: Tue, 27 Oct 2026 03:13:46 +0800 Subject: [PATCH 07/10] docs(463): document core engine and API ownership and verification Split the implementation guide into core, engine and API responsibilities, retain common source/verification/profile rules, and update root workstream and manifest navigation. Document Project Store composition and approved edges. Update maintained guides, crate READMEs, current design navigation and SDK skill references. Preserve historical claims/receipts, archived documents and the reference retirement; link retired source at verified immutable commits. Record every migration part, exact LOC methods, moved/re-covered tests, the fixture-seal path repair, owner gates, branch rebases and external consumer follow-ups. Retain the explicit FP21 FAIL exception and its original evidence. Export and apply exact private cache releases after byte-verifying the archived failure executable; preserve its scratch, sealed SDK bundles and diagnostics. Checks: all 438 local links/anchors in 34 changed documents resolve; one status banner per document; path/command and scope review; whitespace. Rust/runtime checks do not apply to this docs-only change. Completed relocation verification is recorded without turning the FP21 failure into PASS. No tests changed. Production LOC: 102162 -> 102162 (delta +0) Scope: all first-party product implementation, including shipped SQL and JavaScript. before: api 7281, core 38241, engine 56640. after: api 7281, core 38241, engine 56640. Method: tools/production_loc.py --json; exact parent and staged trees; inline tests/comments excluded; shipped SQL and JS included. Counter SHA256: 2903e1aed42f0eebb022b82b5fc2220278ccb870bbc06389adc79c4d340bad59. reference absent (retired R9c; last counted 65,417 at tree 498dd1917812). --- .../references/methods/branch.md | 2 +- .../references/methods/fs-read.md | 4 +- .../references/methods/fs-write.md | 2 +- .../references/methods/project.md | 2 +- .../layerfs-js-sdk/references/rules/cargo.md | 2 +- AGENTS.md | 40 +- api/AGENTS.md | 28 + api/README.md | 2 +- api/binding/tests/README.md | 8 +- core/AGENTS.md | 627 ++---------------- core/README.md | 119 +--- core/crates/layerfs-content/README.md | 5 +- core/crates/layerfs-storage/README.md | 20 +- core/crates/layerfs-telemetry/README.md | 15 +- core/docs/architecture/82-sdk-call-channel.md | 6 +- core/docs/issues/303/02-base-overlay.md | 2 +- core/docs/issues/303/05-fuse-assessment.md | 4 +- .../303/07-implementation-validation.md | 6 +- core/docs/issues/303/fuse.md | 6 +- core/docs/issues/463/IMPLEMENTATION.md | 146 +++- docs/general/benchmark_instruction.md | 16 +- .../general/cas_cdc_deltaencoding_handbook.md | 2 +- docs/general/cleanup.md | 4 +- docs/general/cluster_one_handbook.md | 14 +- docs/general/optimization-guide.md | 4 +- docs/general/optimization-handbook.md | 28 +- docs/general/parallel-worktrees.md | 21 +- docs/general/sandbox-cache-design.md | 20 +- docs/general/sdk.md | 26 +- docs/general/workspace-filesystem-view.md | 4 +- engine/AGENTS.md | 585 ++++++++++++++++ engine/crates/layerfs-persistence/README.md | 2 +- engine/patches/fuser-0.18.0/README.md | 31 +- tools/substitution-proof/README.md | 2 +- 34 files changed, 981 insertions(+), 824 deletions(-) create mode 100644 api/AGENTS.md create mode 100644 engine/AGENTS.md diff --git a/.agents/skills/layerfs-js-sdk/references/methods/branch.md b/.agents/skills/layerfs-js-sdk/references/methods/branch.md index 2427923b3..f254635c7 100644 --- a/.agents/skills/layerfs-js-sdk/references/methods/branch.md +++ b/.agents/skills/layerfs-js-sdk/references/methods/branch.md @@ -2,7 +2,7 @@ > **Status:** Current general guide. Part of the `layerfs-js-sdk` skill. Examples were > captured live in issue #334 Phase A at `b30e4fb8f`. Opaque IDs are shortened; -> the full replies and trace are in `core/target/issue334/phase-a/`. +> the full replies and trace are in `target/issue334/phase-a/`. Examples use `layerfs` as connected in [SKILL.md](../../SKILL.md#connect-to-a-project) and work on the Branch `"work"`. Paging works as described diff --git a/.agents/skills/layerfs-js-sdk/references/methods/fs-read.md b/.agents/skills/layerfs-js-sdk/references/methods/fs-read.md index 1b57bca97..e472c5990 100644 --- a/.agents/skills/layerfs-js-sdk/references/methods/fs-read.md +++ b/.agents/skills/layerfs-js-sdk/references/methods/fs-read.md @@ -2,7 +2,7 @@ > **Status:** Current general guide. Part of the `layerfs-js-sdk` skill. Examples were > captured live in issue #334 Phase A at `b30e4fb8f`. Opaque IDs are shortened; -> the full replies and trace are in `core/target/issue334/phase-a/`. +> the full replies and trace are in `target/issue334/phase-a/`. Examples use `layerfs` as connected in [SKILL.md](../../SKILL.md#connect-to-a-project) and work on the Branch `"work"`. @@ -240,7 +240,7 @@ The output above preserves the Phase A capture at `b30e4fb8f`, which exposed issue #334 BUG-001 by omitting a direct child. After the matcher fix, Phase B step 005 checked `fs.glob('work', 'test/**/*.test.js', '/')` against the new project and returned `items: ['/test/health.test.js']`; its full reply is retained -in `core/target/issue334/phase-b/005-test-m1.out`. The external matcher regression +in `target/issue334/phase-b/005-test-m1.out`. The external matcher regression also covers direct children and several nested levels. ## `fs.diff_files(leftRef, leftPath, rightRef, rightPath)` diff --git a/.agents/skills/layerfs-js-sdk/references/methods/fs-write.md b/.agents/skills/layerfs-js-sdk/references/methods/fs-write.md index 8171f985b..ce7222838 100644 --- a/.agents/skills/layerfs-js-sdk/references/methods/fs-write.md +++ b/.agents/skills/layerfs-js-sdk/references/methods/fs-write.md @@ -2,7 +2,7 @@ > **Status:** Current general guide. Part of the `layerfs-js-sdk` skill. Examples were > captured live in issue #334 Phase A at `b30e4fb8f`. Opaque IDs are shortened; -> the full replies and trace are in `core/target/issue334/phase-a/`. +> the full replies and trace are in `target/issue334/phase-a/`. Examples use `layerfs` as connected in [SKILL.md](../../SKILL.md#connect-to-a-project) and work on the Branch `"work"`. diff --git a/.agents/skills/layerfs-js-sdk/references/methods/project.md b/.agents/skills/layerfs-js-sdk/references/methods/project.md index f2adbfede..410066b73 100644 --- a/.agents/skills/layerfs-js-sdk/references/methods/project.md +++ b/.agents/skills/layerfs-js-sdk/references/methods/project.md @@ -2,7 +2,7 @@ > **Status:** Current general guide. Part of the `layerfs-js-sdk` skill. Examples were > captured live in issue #334 Phase A at `b30e4fb8f`. Opaque IDs are shortened; -> the full replies and trace are in `core/target/issue334/phase-a/`. The client +> the full replies and trace are in `target/issue334/phase-a/`. The client > factories and `list_sandboxes` are #428's; result shapes are unchanged. Examples use `layerfs` as connected in [SKILL.md](../../SKILL.md#connect-to-a-project). diff --git a/.agents/skills/layerfs-js-sdk/references/rules/cargo.md b/.agents/skills/layerfs-js-sdk/references/rules/cargo.md index d1d29637e..707eeb1c3 100644 --- a/.agents/skills/layerfs-js-sdk/references/rules/cargo.md +++ b/.agents/skills/layerfs-js-sdk/references/rules/cargo.md @@ -1,7 +1,7 @@ # Rust and Cargo in a Workspace > **Status:** Current general guide. Live Cargo 1.85.1 checks in issue #337 -> Phase A used product `db5b1bac9`; raw receipts are in +> Phase A used product `db5b1bac9`; at that pin the receipt path was > `core/target/issue337/phase-a/`. These are diagnostics, not benchmarks. ## Put all mutable Cargo state in the view diff --git a/AGENTS.md b/AGENTS.md index beafed0c8..a48027e90 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -2,13 +2,13 @@ > **Status:** Current general guide. -Repository-wide instructions for LayerFS. Also read [core/AGENTS.md](core/AGENTS.md) -for implementation under `core/`. Current owner instructions and documented +Repository-wide instructions for LayerFS. Also read the applicable [core](core/AGENTS.md), [engine](engine/AGENTS.md) +and [API](api/AGENTS.md) guides for implementation in those layers. Current owner instructions and documented supersessions govern; a closed handoff or historical receipt is not a new assignment. ## Product scope and current workstreams -**Implement both cluster one and cluster two in `core/`.** The v0.1.6 +**Implement both workstreams through the core, engine and API layers.** The v0.1.6 reference implementation that lived under root `crates/` was retired on 2026-10-10 (R9c) and is absent at HEAD. It was never a dependency, source include or fallback for core, and must not return as a second product. Its last @@ -20,8 +20,8 @@ simplification. | Workstream | Current scope | Entry point | | --- | --- | --- | -| Cluster one | Implemented content, storage, history, persistence, project Init and telemetry libraries | [Cluster-one handbook](docs/general/cluster_one_handbook.md), [CAS/CDC/delta handbook](docs/general/cas_cdc_deltaencoding_handbook.md) | -| Cluster two | Workspace, FUSE, daemon, execution and Commit/runtime integration design and implementation | [Current design index](core/docs/issues/303/README.md) and its seven primary contracts | +| Cluster one | Core Content/Storage/History/Telemetry algorithms; Engine Persistence and Project Init | [Cluster-one handbook](docs/general/cluster_one_handbook.md), [CAS/CDC/delta handbook](docs/general/cas_cdc_deltaencoding_handbook.md) | +| Cluster two | Engine Workspace/FUSE/daemon/Sandbox; API execution and Commit/runtime integration | [Current design index](core/docs/issues/303/README.md) and its seven primary contracts | | Legacy reference | v0.1.6, retired from `main` by R9c; read at the recovery tag only | [R9c record](core/docs/issues/307/R9C-COMPLETION-20261010.md) | **The LayerFS UI is the dsh LayerFS plugin** (owner, 2026-10-19): the LayerFS tab in @@ -34,7 +34,7 @@ bundle (the LayerFS mock model and its demo workspace) is disabled permanently** (owner, 2026-10-21): it loads nothing, is not released and no guide installs it. Cluster names are workstreams. C1/C2/C5 in older component documents mean -content/storage/history. Check [core/Cargo.toml](core/Cargo.toml) for active +content/storage/history. Check [Cargo.toml](Cargo.toml) for active members: a directory or old test does not establish a built replacement. Source and public contracts establish implemented behavior. Owner requirements and proposals establish target behavior; research establishes neither capability @@ -75,7 +75,7 @@ remains a separate MEMORY/OFF/EXCLUSIVE database file. status and explicit cancellation. The filesystem daemon supervises no commands; optional `WorkspaceApi.exec` only delegates ordinary Sandbox execution. Keep this boundary explicit in implementation - and proofs; see [execution ownership](core/AGENTS.md#filesystem-access-and-execution-ownership). + and proofs; see [execution ownership](engine/AGENTS.md#filesystem-access-and-execution-ownership). - Initial full-root acquisition is explicit. Repeated mount binds the complete root without a whole-tree scan/copy/materialization or dependency restoration. The only file it creates is the Workspace's own overlay database, copied from @@ -100,7 +100,7 @@ remains a separate MEMORY/OFF/EXCLUSIVE database file. canonical construction in Content, object encoding/packing in Storage and database writes in Persistence. Reuse these ports when completing daemon construction; do not add a second encoder or route it through host Init. See - [shared construction boundaries](core/AGENTS.md#shared-construction-and-completion-boundaries) + [shared construction boundaries](engine/AGENTS.md#shared-construction-and-completion-boundaries) for implemented entrypoints and the remaining S10 namespace integration. - `Save::finish()` completes saved objects while the Store remains open; History publication follows. `Handles::seal()` consumes the sole Store @@ -207,7 +207,7 @@ For measurements, read the [agent measurement workflow](docs/general/agent-measu [report template](docs/general/benchmark_agent_report.md) and owning harness/family contract. Benchmark suites, harnesses and released data live in the [layerfs-benchmark](https://github.com/Ephemeral-AI-Lab/layerfs-benchmark) repository, moved out of -`benchmark/` on 2026-10-23. Core routing is its +`benchmark/` on 2026-10-23. Benchmark routing is its [fs-bench-pro/AGENTS.md](https://github.com/Ephemeral-AI-Lab/layerfs-benchmark/blob/main/fs-bench-pro/AGENTS.md). **fs-bench-pro is frozen and left broken (owner, 2026-10-18).** Do not edit, build, run or repair it, and leave it out of workspace builds and checks. Its @@ -300,7 +300,7 @@ remain binding; moving them out of this file does not weaken them. fork, vendor, replace or edit third-party code/registry packages, except the owner's explicitly authorized fuser 0.18.0 timestamp, scoped receive-loop lifecycle and negotiated receive-buffer patches described in - [core provenance checks](core/AGENTS.md#fuser-provenance-and-authorized-patch-checks). + [core provenance checks](engine/AGENTS.md#fuser-provenance-and-authorized-patch-checks). Use locked builds and report an incompatible required dependency with evidence. - One attempted operation; no automatic retry/busy handler, refresh/reprepare or failed-operation replay. Readiness waits are not retries. Preserve exact @@ -309,11 +309,11 @@ remain binding; moving them out of this file does not weaken them. fast lane after each push or pull request (`.github/workflows/ci.yml`: fmt, guards, Clippy and the fast tests) and a nightly lane (`nightly.yml`: slow and FUSE mount tests); `format.yml` checks the Ruff formatting below. - [core/tools/ci_tests.py](core/tools/ci_tests.py) decides which tests go in + [tools/ci_tests.py](tools/ci_tests.py) decides which tests go in which lane. None is a required check, and nothing runs before a push. Do not wait for CI, and do not treat a green run as verification of your change: verify the changed scope yourself with - [core checks](core/AGENTS.md#checks-and-completion) and report checks/gaps. + [product checks](engine/AGENTS.md#checks-and-completion) and report checks/gaps. There is still no pre-push gate: `tools/preflight.sh` stays retired; do not restore it or an equivalent wrapper. An empty guard scan proves no implementation. @@ -345,9 +345,9 @@ remain binding; moving them out of this file does not weaken them. no `fsync`/`fdatasync`/`sync_data`/`sync_all` on disposable Workspace backing, and no space is reserved ahead of use on it. Memory hints are hints, not evidence of resident bounds. -- New core/application production files obey the 999-line ceiling and 200-line +- New core/engine/API production files obey the 999-line ceiling and 200-line declaration/delegation ceiling for `lib.rs`/`mod.rs`. Product-only source, - external tests and guard coverage are detailed in the core guide. + external tests and guard coverage are detailed in the layer guides. - Format changed Python tools with Ruff; `ruff.toml` names the pinned version, scope and command. `format.yml` reports formatting drift after a push; nothing runs before one. @@ -442,7 +442,7 @@ renderer highlights what changes: counted; name their directory in prose if it matters. A listing is a snapshot. It does not make a planned name a scaffolding -requirement, and an existing source file or `core/Cargo.toml` still decides +requirement, and an existing source file or `Cargo.toml` still decides what is built. ## 5. Why these rules exist (worked example) @@ -450,3 +450,13 @@ what is built. The historical cache-credit failure and its immutable ledger remain linked in [the measurement workflow](docs/general/agent-measurement-policy.md#5-why-these-rules-exist-worked-example). Historical explanation is retained outside default implementation routing. + + +All product layers follow the detailed +[production source rules](engine/AGENTS.md#production-file-size-and-responsibility) +and [checks and completion rules](engine/AGENTS.md#checks-and-completion). +The root manifest builds four core crates, nine engine crates, `layerfs-api` +and the Node binding. The dependency direction is `core < engine < api`, including +dev dependencies and test includes. Workstream names do not change this layering. +After rebasing across #463, update each selected worktree's own target registration and prepare again +for the root `target/` path; never migrate another worktree's resource record. diff --git a/api/AGENTS.md b/api/AGENTS.md new file mode 100644 index 000000000..6b55bd674 --- /dev/null +++ b/api/AGENTS.md @@ -0,0 +1,28 @@ +# Agent rules for API + +> **Status:** Current general guide. + +Read [repository instructions](../AGENTS.md) first. This layer contains +`layerfs-api`, the Node binding (`layerfs-node` under `binding/`) and the +JavaScript packages. The [root Cargo manifest](../Cargo.toml) and +[SDK guide](../docs/general/sdk.md) establish the built Rust members and public +surface. API may depend on engine and core; dependencies and test source includes +from either lower layer back into API are forbidden. + +Project Store Init and install belong to `layerfs-project::store`; the Rust API +retains its public re-exports and the binding makes one direct Project Init call. +SDK-facing daemon integration tests live in `layerfs-api/tests`, with cheap +includes of lower-layer daemon fixtures. Build the ordinary daemon binary before +running tests that launch it. `LAYERFS_TEST_DAEMON` may select an explicit binary; +otherwise the tests locate the sibling Cargo output. The native binding's +[external proof guide](binding/tests/README.md) describes its Linux addon tests. + +All API product code follows the +[production size and responsibility rules](../engine/AGENTS.md#production-file-size-and-responsibility) +and [checks and completion rules](../engine/AGENTS.md#checks-and-completion), +including bounded test commands, build-before-run, locked dependencies, ARM64 +flags, per-commit LOC and the Disposable-only profile. Preserve the existing +unsafe-code boundaries; do not add test hooks or inline tests to production src. +The owner leaves Node binding/JavaScript CI targets excluded; changed scope must +still be verified explicitly. The named SDK mount tests remain in nightly's +Linux mount lane. CI reports and does not gate a push. diff --git a/api/README.md b/api/README.md index b7d09b250..ea6623d54 100644 --- a/api/README.md +++ b/api/README.md @@ -8,7 +8,7 @@ This is the wiki for `api/`, LayerFS's JavaScript packages: what each one is for, which one you need, and how they are built and tested. How to use each -one is in [`how-to-use/`](how-to-use/): +one is in [`how-to-use/`](how-to-use): | Guide | Package | What it does | Who uses it | | --- | --- | --- | --- | diff --git a/api/binding/tests/README.md b/api/binding/tests/README.md index aaf03096c..75af6d4e5 100644 --- a/api/binding/tests/README.md +++ b/api/binding/tests/README.md @@ -8,10 +8,10 @@ add a test-only product API. Build `layerfs-node` first, then compile the test targets with `--no-run` before running them under an explicit wall timeout: ```sh -cargo +1.85.1 build --manifest-path core/Cargo.toml --locked -p layerfs-node -cargo +1.85.1 test --manifest-path core/Cargo.toml --locked -p layerfs-node --tests --no-run -timeout 30 cargo +1.85.1 test --manifest-path core/Cargo.toml --locked -p layerfs-node --test native_discovery -timeout 90 cargo +1.85.1 test --manifest-path core/Cargo.toml --locked -p layerfs-node --test native_admission +cargo +1.85.1 build --manifest-path Cargo.toml --locked -p layerfs-node +cargo +1.85.1 test --manifest-path Cargo.toml --locked -p layerfs-node --tests --no-run +timeout 30 cargo +1.85.1 test --manifest-path Cargo.toml --locked -p layerfs-node --test native_discovery +timeout 90 cargo +1.85.1 test --manifest-path Cargo.toml --locked -p layerfs-node --test native_admission ``` Use the worktree's registered Cargo resources for these commands. Node 20 or diff --git a/core/AGENTS.md b/core/AGENTS.md index a0bbf348f..450771bd8 100644 --- a/core/AGENTS.md +++ b/core/AGENTS.md @@ -2,583 +2,56 @@ > **Status:** Current general guide. -Read [repository instructions](../AGENTS.md) first. This file adds implementation -boundaries for both current workstreams under `core/`; it does not repeat the -product mental model or campaign-specific benchmark procedures. - -## Scope and ownership - -- Implement cluster one and cluster two in `core/`. The v0.1.6 reference under - root `crates/` and the archived `core/reference-tests` were retired by R9c - (2026-10-10) and are absent at HEAD; recover them at - local tag `reference-v0.1.6-final` (`d296981ac`, `crates` tree `498dd1917812`). - Neither was a dependency, source include or fallback; do not restore them. -- Active cluster-one members are content, storage, history, persistence, project - Init and telemetry. The initial cluster-two SQLite engine is `layerfs-overlay`; - its active membership does not complete Workspace/FUSE/daemon integration. - [core/Cargo.toml](Cargo.toml) is the membership authority. - Workspace now exposes immutable base binding/read, effective source-qualified - lookup/stat/paged name merge, prepared actor install and atomic ordinary - namespace operations, bounded writes/truncate/regrow and composed payload - reads. Independent file/captured/operation custody and bounded live reclamation - are implemented through S6, including indexed automatic reclamation (its - physical reservation and headroom were removed by #321: no space is reserved - ahead of use, and a full device rolls the write back as no space); - native/runtime/integrated exits remain - unfinished. See [S6 audit](docs/issues/307/S6-EXIT-AUDIT.md). Its relocated - predecessor `layerfs-workspace-legacy` was removed by R7-retire. - Since #321 the daemon holds one overlay file and connection per mounted - Workspace, each behind its own lock, with the calling thread running each - short job; the fair SQL owner thread, its queue, credits and shared memory - budget are removed. See the [terminology guide](docs/architecture/64-overlay-terminology.md) - and the [#321 record](docs/issues/321/CHECKLIST.md). - Daemon also exposes a direct global Store adapter with a - mount-time reader per Workspace, exact quarantine and read-only bind snapshots, - one immutable cache shared across Workspaces, bounded root - binding and operation-owned exact failures. Concrete opening stays outside - the provider-independent adapter; see the - [direct Store boundary](docs/architecture/61-direct-store-adapter.md). - The host-mediated SDK/upstream transport is retired; see - [the retirement record](docs/issues/307/PRE-S8-F12-20261007.md). - Workspace calls return typed values directly and count SQL/payload/allocation - work under the same lock. Exact attempted failures retain their cause and - backing; before-effect refusals retain their original input. Overlay/Daemon - also expose bounded indexed operation records in the same database, with guarded atomic changes and automatic last-owner - cleanup. Content now exposes a backed file editor over these records and - Workspace supplies an explicit operation/file adapter with first-original - failure custody. Run-aware localized edits reuse the frozen sparse scanner - and bounded positive immutable zero evidence. Streamed directory inputs share - the canonical filesystem algorithm; backed serial state supplies new-parent - membership, rebuilt roots and initial counts/final row streams. On the backed - route validation classifies in 64-row windows and keeps its topology evidence - in indexed records; resident routes keep their resource-derived limits. - Captured local inode/run points retain exact reader root/floor and bounded - forward metadata progress. Captured regular-file normalization now derives - authenticated base facts, coalesces final changes into indexed records and - consumes them once through the retained FileView/fallible edit source. Backed - reference reduction/release uses fixed rows, sealed membership passes and - guarded FIFO/cursor transitions. Captured namespace normalization is the - `CapturedNamespace` producer - ([captured namespace construction](docs/architecture/78-captured-namespace-construction.md)); - the product Commit constructor calls it - ([product Commit](docs/architecture/79-product-commit.md)). The Store - half of Commit is implemented with exact original failure/unknown custody; - see [Store Commit](docs/architecture/65-store-commit-composition.md). - The external E01 example records original startup work, diagnostics and Stop - without creating a Workspace route. It supplies diagnostic receipt consistency, - not E1/E2 performance admission. Its relocated predecessor was removed by - R7-retire; standalone native executable/Exec integration is unfinished. - Pre-S8 direct-operation accounting now has actual registered macOS/Linux engine - and Store-half Commit runs, independent family/count validation, and supported - phase observations. Numerical latency/residency and exact continuous peaks - remain unqualified; see the [accounting scope](docs/issues/307/PRE-S8-F14-20261007.md). - SDK creates/imports the initial Store, publishes the first Branch and consumes - seal, returning a closed file plus explicit provider/locator/profile metadata. - It retains no Store handle or data service. Native install now streams the - sealed file once, opens it in the daemon and returns both actual SQLite versions; - see [F5 handoff](docs/issues/307/PRE-S8-F5-20261007.md). Authenticated mount - binding, Store-half Commit, status, terminal close, fork and history now compose - the direct ports; see [native control](docs/architecture/68-native-workspace-control.md). - The prior client/runtime, daemon upstream, Bridge logical data framing and - excluded API-core are retired. Historical receipts keep their original topology - and verdicts. R7-retire (2026-10-10) - removed all seven excluded directories as retirement: `layerfs-server`, - `layerfs-fuse-legacy`, `layerfs-sandbox-legacy`, `layerfs-sdk-legacy`, - `layerfs-daemon-legacy`, `layerfs-bridge-legacy` and - `layerfs-workspace-legacy`. `core/crates` now holds only the 13 active - members; the boundary guard refuses the return of a removed directory or - package name, and each source is recoverable from the commit named in the - [R7-retire record](docs/issues/307/R7-RETIRE-COMPLETION-20261010.md). - Pinned read-only SDK views (303/08 O-10) are deferred, not dropped: no - implementation is in the tree, and a kept feature needs a new design on the - SQLite overlay. Do not restore the predecessor code to supply them. - Project native import preserves opaque symlinks, complete membership and hard - links, with indexed acquisition state. The accepted host WAL baseline retains - its recorded speed FAIL; no new timing is implied by SDK composition. - Bridge retains pinned authenticated KK channels, bounded native records and - independent fences and bounded native install/control. FUSE/Exec qualification - and complete kernel mount readiness remain S8. - The replacement Sandbox is an active member with ordinary Engine execution, - owned lifecycle and authenticated SDK/daemon startup. Optional privileged - command cancellation/client provenance is outside the current owner scope. - The replacement Fuse is now active with a fixed shared dispatcher, actual - deferred Owner/Store ports, a read-path callback adapter with complete opcode - accounting, direct mount/session ownership and connection drain. - Its predecessor `layerfs-fuse-legacy` was removed by R7-retire; the last - commit holding that source is `15e33e22c`. The daemon - composes Attach/Locate/Ready and reversible normal unmount; see - [native request service](docs/architecture/75-native-request-service.md) and - [native mount session](docs/architecture/76-native-mount-session.md). - Ordinary native mutation is served through the existing Workspace plan and - one publishing Overlay job, with no notification and no writeback cache; see - [native mutation and kernel coherence](docs/architecture/77-native-mutation-coherence.md). - A control Commit runs the captured namespace producer through the unchanged - driver, and takes the Workspace's overlay lock for each of its jobs; the mounted - proofs and their limits are in the - [R5 record](docs/issues/307/R5-COMPLETION-20261009.md). Forced unmount of one - Workspace is implemented as `ForceUnmount`: a before-effect guard, one abort - write on the connection's own control, the terminal fence, the local drain, - one plain detach, then Revoke and Close; see - [forced teardown](docs/architecture/80-forced-teardown.md). It is refused where - no abort control is bound, which includes the current Sandbox topology, and a - stop after an effect is `Retained` with no way back. No daemon-wide graceful - drain exists and none is planned. Source acquisitions have their own owner - slots, and a failed cold read ends its own request with `EIO` while the - mount keeps serving; the concurrency, teardown and failure-scope proofs and - their limits are in the [R6 record](docs/issues/307/R6-COMPLETION-20261009.md). - A create that leaves fewer unconsumed inode serials than the daemon's - configured low-water makes one early reservation; every deployment and - harness sets 0 today, which makes none. A new Mount is refused `Capacity` at - `mount:debt` while maintenance is stopped. Both, the proofs added around - them and the rows still open are in the - [R8b record](docs/issues/307/R8B-COMPLETION-20261010.md). R8b closed not - qualified and R9b without removal. R8c then closed qualified on function, - counts and resources at the owner-rescoped scope, with the deployed - low-water at 256 ([R8c record](docs/issues/307/R8C-COMPLETION-20261010.md)), - and R9c retired the root reference - ([R9c record](docs/issues/307/R9C-COMPLETION-20261010.md)). - Add members only with real product boundaries and implementation. -- Cluster-one work starts with the [handbook](../docs/general/cluster_one_handbook.md) and - [CAS/CDC/delta guide](../docs/general/cas_cdc_deltaencoding_handbook.md). Use public contracts, - source pins and limitations; preserve canonical compatibility. -- Cluster-two work starts with the [current design index](docs/issues/303/README.md) - and relevant primary operation/engine/FUSE contracts plus - [runtime integration](docs/issues/303/06-cluster-one-integration.md). - Required corrections are real engineering scope; research candidates are not - implemented features or excuses for accumulated workload caps. -- Closed Stage 0–6 handoffs and prior server/backend plans are historical. - Consult them for a selected compatibility/reference question; do not restart - their loops or inherit their retired topology. Do not revive `layerfs-server`. -- Keep unrelated work intact. Migration, source moves and retirement are explicit - changes, not side effects of implementing a component. - -## Architecture and public contracts - -Overlay schema19 uses `directory_entry` and `operation_record` terminology, -including owned/indexed variants, throughout SQL and the active public ports. -Through schema 33 Workspaces shared physical tables partitioned by namespace; -since #321 (schema 34) every mounted Workspace has its own file with the same -tables, copied from a closed empty template at mount and deleted at terminal -unmount. The naming -change authorizes no physical table redesign; generic temporary buffers and -historical receipts retain their distinct terms. See the -[terminology guide](docs/architecture/64-overlay-terminology.md). -The #320 product sweep (2026-10-14, schema 37) removes accounting triggers, -Workspace/allocator SQL rows and generic caller-minted leases. Workspace -lifecycle/frontier/dirty/base-reader counters are one journaled runtime value, -restored only after known whole-job rollback; unknown outcomes retain custody. -Commit runs/readers/base pins are journaled owner maps; captured generation -holds use a count index. Daemon-bound routing is checked once per call; Overlay -accepts no Route and stores no namespace. Cleanup debt remains SQL-backed after -the [memory-placement review](docs/issues/320/CLEANUP-MEMORY-DESIGN-20261014.md). -Resources computes row/length totals on demand and -retains exact owner counts from memory. See the current -[runtime state](docs/architecture/64-overlay-terminology.md#runtime-workspace-state-and-remembered-sql-custody). - -Schema17 adds native mount/source/lookup/read associations, atomic Workspace -read observations and bounded revoked-lookup retirement. Schema18 adds native -file associations over the existing OpenFile owner and atomic open decisions; see -[native read custody](docs/architecture/73-native-read-custody.md). This component -does not establish Ready, kernel service or full drain. Schema19 adds native -directory ownership, exact name-boundary cookies, retained parent updates and -bounded live cleanup; see [directory custody](docs/architecture/74-native-directory-custody.md). - -`docs/architecture/` describes product source, not release qualification. -A source change to boundaries, canonical/physical format, algorithm or named -bound updates the affected architecture/API document in the same change. -Record source pins and advance them explicitly; never silently re-date evidence. -Keep implementation description separate from target proposal and research. - -Public content/storage/history/persistence contracts govern integrated callers. -Stable capture/input, Store-derived policy, backpressure, Save completion and -atomic history publication are separate obligations. Branch Commit overwrites the -head and keeps its captured parent; see the [owner supersession](docs/issues/307/BRANCH-OVERWRITE-DECISION-20261007.md). Immutable objects do -not replace authority, reference closure, mutable history or safe GC. - -Engine-independent Project logic may consume SQLite-backed acquisition through -an owning backend-neutral port. Concrete SQL and database ownership belong in -Persistence/application composition along the permitted dependency direction. -A guard refusal of Project's direct engine dependency identifies wrong placement; -resolve that boundary before proceeding. It does not require replacing indexed -backing with a custom sorter. The port and its SQLite provider now exist as an -opt-in Store schema ([acquisition backing](docs/architecture/44-acquisition-backing.md)), -and Project's import runs on that port alone -([backed acquisition](docs/architecture/43-backed-initial-acquisition.md)). Do not -weaken the boundary guard, give Project an engine dependency or reintroduce a -second acquisition algorithm. -See the [S7/S9 remaining plan](docs/issues/307/IMPLEMENTATION-PLAN-S7-S9-20261006.md). - -### Filesystem access and execution ownership - -Owner clarification 2026-10-08: these are implementation and proof requirements, -not a claim that S8 or S10 is qualified. FUSE serves any permitted process that -can see the mount. Request admission and Workspace mutation/capture must not -require an Exec identity, registered command or LayerFS-launched parent. -Apply the same permissions, filesystem semantics and ownership to external -executors, interactive shells and ordinary Sandbox execution. - -Sandbox setup or the external executor establishes command identity, mount -visibility and protection of Store, Overlay and daemon credentials. Ordinary -runtime execution owns standard I/O, exit status and caller-requested cancellation. -SDK public organization is the eleven operations documented in -[the implemented SDK surface](../docs/general/sdk.md), with operation files under -[layerfs-api/src](crates/layerfs-api/src/). Project offers init/fork/ -branches/commits; Sandbox offers create/close; Workspace offers mount/exec/ -commit/status/unmount. Shared control/recovery/diagnostic plumbing lives in -base/ and the hidden internal module. Optional WorkspaceApi.exec selects the -mounted directory and delegates the existing Sandbox launcher; -the daemon has no exec/supervisor, launcher mode, per-Exec cgroups, command -registration or custom Exec stream/status/cancellation protocol. - -FUSE owns exact request/open/lookup/capture/Commit lifetimes and complete -filesystem/daemon-work drain. Zero registered commands or shell exit is never -evidence of released descriptors, mappings, kernel references or daemon jobs. -Forced filesystem teardown does not implicitly kill caller-owned processes. -Normal unmount uses a reversible kernel busy probe while ordinary service stays -usable. Force refuses active namespace control producers before any effect. - -Commit consumes the Workspace's published frontier through the shared Content, -Storage and Persistence pipeline regardless of launch route. stdout/stderr are -not filesystem state unless the command writes them to a file in the Workspace. -The old proposed managed-daemon Exec selections are withdrawn prospectively; -retain their original IDs, source pins, receipts and verdicts. Ordinary runtime -stream/result correctness and filesystem-lifetime proofs keep their real owners. - -S8 verification must include a process launched outside the Exec API, with no -Exec registration, reading and mutating the mount and retaining a filesystem -reference during an unmount attempt. S10 must prove that such changes survive -Commit and a fresh mount. Use ordinary public filesystem access in these proofs. - -Reviewed target source ownership2026-10-08: the replacement `layerfs-fuse` owns -its complete native connection/request service, including bounded dispatch, -parking/resumption, kernel handlers/replies and coherence. Daemon assembles one -shared Fuse service with its existing SQL/Store services, retaining registry, -overall Ready/unmount and Commit composition. Dependency is daemon -> fuse -> -workspace, never Fuse -> daemon. Request dispatch/read ports, mount/Ready and -per-Workspace normal drain are implemented ([R2 record](docs/issues/307/R2-COMPLETION-20261008.md)), -as is ordinary native mutation ([R3 record](docs/issues/307/R3-COMPLETION-20261008.md)); -as is the captured namespace producer with its bounded validation -([R4 record](docs/issues/307/R4-COMPLETION-20261008.md)), which the Commit -driver reaches through the product constructor -([product Commit](docs/architecture/79-product-commit.md)). See the -[reviewed ownership](docs/issues/307/R2-R5-SOURCE-OWNERSHIP-REVIEW-20261008.md). -Moving blocking OwnerClient calls behind a port does not establish deferred service. - -### Shared construction and completion boundaries - -Source checked at `5747f0119`, guidance updated 2026-10-08. Namespace Init and -daemon construction share Content, Storage and Persistence through their public -ports. Their input adapters and publication lifecycles have distinct owners: - -| Input/operation | Existing route | -| --- | --- | -| Native Init file | Project import calls Content `construct_stream`; bounded output batches feed `Save::accept` | -| New captured file | Workspace `CapturedFileEdits` calls Content `construct_runs` over data/zero windows | -| Existing captured file | The same adapter calls `apply_indexed_edits_view_backed` over an authenticated retained `FileView` and normalized final edits | -| Initial namespace | Project streams acquired bindings/inodes through Content directory/table builders | -| Captured namespace | Workspace `CapturedNamespace` seals headers, typed values and fresh ranks into indexed records and calls Content `update_filesystem_streamed_backed`; names come from the retained captured reader | -| Captured symlink and metadata | The same producer calls Content `emit_symlink` for a fresh target and patches or builds the portable attribute tree; a stored symlink keeps its base content root | -| Object output | Content emits `FinalizedObject`; Storage `SaveSink` implements `FinalizedConsumer` by forwarding to `Save::accept` | - -Use the actual Store-derived construction policy and bounded capacities on -both routes. Fresh construction and incremental edits use appropriate public -entrypoints and common canonical formats; do not assume an incremental file root -must equal a fresh full reconstruction, since retained chunk boundaries can differ. -Overlay owns mutable payload, metadata, operation records and construction scratch -under Workspace prefixes. Content owns canonical algorithms; Storage owns -deduplication, encoding and packs; Persistence owns global Store writes. Keep -SQLite types and paths out of Content and the daemon's provider-independent -`store/` adapter. Do not materialize a native tree or invoke Project Init to -implement a Workspace Commit. Native Init acquisition backing remains a separate -host provisioning facility. - -Current source has captured-file normalization and the Store half of Commit. -`BoundWorkspace::commit` captures once, begins a Save, invokes a caller-supplied -Content constructor, finishes the Save, publishes through History and installs -the known root locally. Full captured namespace assembly, including names, -links, metadata and changed file roots, is -[`CapturedNamespace`](crates/layerfs-workspace/src/construction/driver.rs). -The product constructor `BoundWorkspace::commit_captured` runs it inside that -driver: it acquires the captured reader and one operation owner, hands the -driver the original cause on failure, and releases both owners only after the -driver's outcome is known, keeping them with the failure when it is not -([product Commit](docs/architecture/79-product-commit.md)). A control Commit -uses it; `Service::execute` still takes a caller's constructor for driver tests. -See [captured-file construction](crates/layerfs-workspace/src/construction/captured/owner.rs), -[the shared Save sink](crates/layerfs-storage/src/save/operation.rs) and -[Store Commit composition](docs/architecture/65-store-commit-composition.md). - -Keep completion boundaries explicit: `Save::finish()` completes object storage; -Init then initializes history, while Commit calls `commit_branch` against its -expected head before local base installation. SDK Init subsequently calls `Handles::seal()` to -checkpoint, close and hand off one Store file. The macOS allocation correction -runs only at this sole-owner Store seal; it is not a Content/pack format change -or live-daemon maintenance. Linux daemons keep their shared Store open. The -[seal proof](docs/issues/307/SEAL-ALLOCATION-STRIDE1-20261007.md) retains its exact -platform and benchmark scope; it does not qualify daemon allocation or S10. - -## Optimization and performance debugging - -Before changing a performance-sensitive path or diagnosing a performance finding, -read the [optimization guide](../docs/general/optimization-guide.md). Its FUSE, -SQLite and complexity rules are mandatory: reject quadratic or worse scaling, -use SQLite-backed mutable indexes/state rather than custom duplicate trees/graphs, -and account for request/SQL/IO/copy/residency/cleanup work. Preserve cluster one's -canonical formats and public APIs; use count-driven evidence and the existing -measurement policy. SQLite debugging/optimization claims require both database -EXPLAIN and correlated runtime database profiling; overall wall time or a plan -alone is insufficient. An unrelated/docs-only change does not require a campaign. -The [optimization handbook](../docs/general/optimization-handbook.md) is the -working procedure on top of those rules: the counters that already exist, the -diagnostic groups, the scaling checks and the current candidate list. - -## Product source and external verification - -`core/crates//src/` contains production code exclusively, including -included/generated implementation. Runtime SQL and other shipped implementation -have the same ownership rules. - -Forbidden in product source: inline tests/benches, test-only cfg/features, -fixtures, mocks, fake clocks, fault injection, test/benchmark drivers, test-only -public APIs, benchmark-selected algorithms and executable rustdoc test blocks. -Platform cfgs, real features, production validation/invariants and actual telemetry -remain legitimate. Put API documentation with the API; examples outside src. - -| Content | Location | -| --- | --- | -| Product implementation | `core/crates//src/` and required runtime source | -| Public-API tests and their helpers/fixtures | Package `tests/` | -| Runnable examples | Package `examples/` | -| Package benchmarks | Package `benches/` | -| Product-wide harness/diagnostics | the [layerfs-benchmark](https://github.com/Ephemeral-AI-Lab/layerfs-benchmark) repository; inspect the actual harness manifest/entrypoint | -| Development checks | `core/tools/` | - -Tests exercise the production library that normal consumers use. Do not -include/recompile private source, redirect target paths into test directories, -import helpers into production or expose an API only to enable a test. -Test-only dependencies belong in dev-dependencies; retain component-specific -restrictions, including std-only telemetry. - -Prefer deterministic public behavior and external observations. Telemetry tests -can use completed reports and structural ordering; do not add a product fake-clock -interface or narrow sleep-based wall thresholds. Verify disabled behavior through -its actual allocation/clock path. Scaffold no empty placeholder directories. - -## Production file size and responsibility - -All new replacement/application-adapter production files have at most **999 -physical lines**, including comments/blanks. This includes required runtime SQL -or other shipped formats outside Rust src. Extend guard coverage for new formats; -moving implementation does not evade the rule. The legacy root source is -retired; do not recreate a root `crates/` for product work. - -Every product `lib.rs`/`mod.rs` has at most **200 physical lines**. These files -contain attributes, declarations, imports/reexports, API docs and thin forwarding. -Definitions, impls, state/constants encoding behavior, branching, loops, conversions, -validation, formatting and I/O belong in focused named implementation files. - -Split by responsibility before the ceiling: lookup, transactions, reconstruction, -placement and ownership, not numbered files or a renamed god module. Use ordinary -functions/concrete types; do not add a factory/interface per algorithm or a -service locator. Keep actual process/provider boundaries independently usable. -Do not minify, expand macros or add includes to evade size/ownership rules. - -Physical line ceilings differ from production LOC. Follow the root -[per-commit LOC policy](../AGENTS.md#production-loc-comparison-for-every-commit) -using exact parent/staged/committed trees and migration subtotals. Docs, tests, -fixtures, examples and tools do not contribute to production LOC. - -## Failure, persistence and dependencies - -- One attempted operation; no automatic retry, busy handler, refresh/reprepare, - error-driven algorithm/backend/reference substitution or guessed recovery. - Readiness waits and explicit cancellation have their own state before an - attempt; they do not permit replay after failed/unknown publication. -- Preserve definite-failure atomicity, original errors and exact uncertain - custody. No resend, rollback/delete or success claim based on an unfenced read. -- Global Persistence uses **Disposable/WAL/OFF only**, on macOS and Linux, - under the [owner's active-profile rule](../AGENTS.md#active-persistence-profile--owner-direction-2026-10-07). - Durable execution is disabled indefinitely until explicit owner reauthorization; - retained Durable source may compile but no test, diagnostic, measurement or - application invocation may execute it. Select Disposable explicitly rather than - relying on a default argument. Disposable claims process-crash survival only. - Open verifies WAL and never converts an - existing Store. Select profile/layout before open; Postgres stays unavailable. - Owner supersession2026-10-07 keeps WAL throughout Init and Commit; no private - MEMORY import or journal promotion remains. The measured host Init regression - is retained as FAIL and accepted as the new baseline for that exact scope. - Host seal consumes sole ownership, checkpoints, closes and verifies one file. - Its macOS completion releases unused extents beyond logical EOF through the - existing safe nix API, preserving the original file's bytes and identity. - This narrow seal-only correction does not restore per-pack preallocation or - the allocation owner, and is never invoked on a live shared daemon Store; see - the [seal boundary](docs/architecture/60-shared-store-foundation.md). - See the [foundation checkpoint](docs/issues/307/PRE-S8-F1-F4-20261007.md). -- Target (owner direction 2026-10-07): the same Store opened directly by every - Linux daemon from a shared volume, several writer processes, no host in the - data path, using only Disposable/WAL/OFF. A contended - write still has one SQL attempt and exact failure/unknown custody. Owner - clarification2026-10-12 requires one ongoing Commit per Workspace and allows - concurrent Commits on different Workspaces. Bounded before-effect admission - now queues SQL work within a Session and coordinates short Linux writer jobs - on the existing local Store parent-directory inode; multiple Store files in - one directory share this coarse short-transaction lane. Do not open/close a - separate main/WAL/SHM descriptor for advisory ownership: closing a main-file - descriptor can cancel SQLite's own process POSIX locks. This admission does - not gate whole Saves or Commits or replay - a failed SQL attempt. macOS has Session admission only; separate macOS writers - and uncoordinated raw SQLite writers retain exact Busy refusal. Follow the - [integration contract](docs/issues/303/06-cluster-one-integration.md) and its - [deepest-file plan](docs/issues/307/SERVERLESS-STORE-PLAN-20261007.md); do not - extend the host-mediated SDK runtime, Bridge data codec or daemon upstream. -- Store concurrency (owner decision 2026-10-18): one global database and one - writer at a time are the design, not a limitation to engineer around. Keep - the existing admission, directory lock and publication lane; shorten what - runs inside the lane (only head check, merge and publish) instead of adding - writers or databases. Judge speed on uncontended calls; contention must stay - correct, bounded and exact. See the - [Store concurrency model](docs/architecture/83-store-concurrency-model.md). -- The daemon overlay is a separate owner/profile from global persistence: - one local database file per mounted Workspace, opened MEMORY/OFF/EXCLUSIVE by - one connection behind that Workspace's lock. Workspaces share no overlay - connection, page cache or memory budget. It is not an implemented distributed Store or a universal - global-Store rule; reader-pool alternatives need their own proofs. -- WAL/sync are permitted for a declared global Store profile. Do not add - fsync/fdatasync/sync_data/sync_all on disposable Workspace backing. Memory - hints do not prove bounds. Claim only actual completion/durability contracts. -- No third-party patch, fork, vendor, registry edit or replacement dependency, - except the owner's fuser 0.18.0 signed-timestamp correction below. - Use existing capabilities and locked builds; report an incompatible required - dependency with source evidence. Unsupported required platforms/capabilities - fail explicitly, not via a silent no-op or fallback. +Read [repository instructions](../AGENTS.md) first. Core contains the four +algorithm and contract crates: Content, History, Storage and Telemetry. The +[root workspace manifest](../Cargo.toml) decides membership. + +## Scope and dependencies + +Core depends only on core, including build and dev dependencies and test source +includes. It has no rusqlite dependency. The +[boundary guard](../tools/check_product_boundary.py) checks every crate against +one layer map and exact production-edge allowlist; unknown crates fail closed. +Engine composition belongs under [engine/](../engine/AGENTS.md), and public SDK +composition belongs under [api/](../api/AGENTS.md). Neither layer is a fallback +implementation for core. The retired v0.1.6 reference remains absent; its recovery +tag and historical evidence are described in the root guide. + +Start with the [cluster-one handbook](../docs/general/cluster_one_handbook.md) +and [CAS/CDC/delta guide](../docs/general/cas_cdc_deltaencoding_handbook.md). +Preserve canonical compatibility, public ports, source pins and limitations. +For Workspace integration also read the +[current design index](docs/issues/303/README.md) and the relevant primary +contracts. Research and old Stage handoffs do not select new algorithms or +reopen a closed campaign. + +## Construction and completion boundaries + +Content owns canonical filesystem/file construction. Storage owns encoding, +packing and object read/write ports. History owns publication and mutable +history contracts. Telemetry owns observations and timing. Project adapts native +inputs; Workspace adapts an immutable base plus captured Overlay changes. They +reuse the same Content and Storage pipeline. See the engine guide's +[shared construction boundaries](../engine/AGENTS.md#shared-construction-and-completion-boundaries). +Do not add a second encoder, constructor or source include to supply integration. + +Storage keeps its narrowly audited FFI module `src/encoding/codec.rs` under +`deny(unsafe_code)`; Content and Telemetry forbid unsafe code. Preserve the +existing unsafe boundaries and extend guard coverage when required shipped +formats are introduced. No third-party source or dependency changes are implied. ## Checks and completion -Run commands from the repository root with the actual core manifest. For product, -API, manifest or runtime-source changes, cover tests/examples, warning-denying -Clippy and formatting, plus the boundary guard and its self-tests: - -```sh -cargo +1.85.1 test --manifest-path core/Cargo.toml --locked --all-targets -cargo +1.85.1 clippy --manifest-path core/Cargo.toml --locked --all-targets -- -D warnings -cargo +1.85.1 fmt --manifest-path core/Cargo.toml --all -- --check -python3 -B core/tools/check_product_boundary.py -python3 -B -m unittest discover -s core/tools -p 'test_*.py' -``` - -Every test invocation obeys the repository's -[2-minute test ceiling](../AGENTS.md#4-code-build-and-docs): run it under an -explicit timeout of at most 120 s, per package when the whole suite cannot fit, -and treat reaching the ceiling as a hang to diagnose, not a run to wait for. - -Migrations and refactors follow the root -[delete-rather-than-nurse rule](../AGENTS.md#4-code-build-and-docs): delete a -test that is tricky to adapt, keep or move only cheap tests of surviving -behaviour, and re-cover any still-valid fix or contract on the new code. -fs-bench-pro (in layerfs-benchmark) is frozen and left broken (owner, 2026-10-18): -do not build, run, check or repair it. - -For docs-only changes, check links/anchors, status/claim accuracy and whitespace; -report why Rust/runtime checks are inapplicable. For tooling/harness changes run -the owning scoped tests. At final implementation identity run required covering -checks once; diagnose a failure from its output/source before a justified repair -and rerun. Do not repeat unchanged passing checks or run an unrelated legacy sweep. - -The guard checks source text, line caps and common prohibited constructs, -including markers embedded in source comments/strings. It is not a Rust semantic -or runtime proof. Review ordinary macros, helpers, dependency/target declarations -and generated inputs; extend scanners for new shipped formats. An excluded -FUSE/daemon package is not exercised by passing active-workspace tests. - -CI reports after a push and never gates it (see the -[root rule](../AGENTS.md#4-code-build-and-docs)); test lane selection is -[tools/ci_tests.py](tools/ci_tests.py). When a test target is renamed, moved or -measured at 5 s or more, update its `SLOW` list; Linux-only daemon targets go to -the nightly mount lane automatically. There is no pre-push gate; -`tools/preflight.sh` is retired. Do not disable discovery or recreate an -equivalent wrapper. Report exact checks, failures and gaps. A scan or proposal -alone does not establish implementation. - -### Build flags are part of the check - -aarch64 binaries retain the repository ARMv8 AEAD build inputs: -`--cfg aes_armv8 --cfg polyval_armv8 --cfg chacha20_force_neon --C target-feature=+aes,+sha2`. -The [root Cargo config](../.cargo/config.toml) is discovered from the working -directory, not by a manifest path into core. Builds outside the repository or -with explicit RUSTFLAGS must repeat that profile. Record flags/config in build -identities; preserve the transport's required-profile refusal when integrating -it. Documentation builds do not prove the binary profile. - -Measurement work additionally follows the -[agent measurement workflow](../docs/general/agent-measurement-policy.md) and -[owning core harness guide](https://github.com/Ephemeral-AI-Lab/layerfs-benchmark/blob/main/fs-bench-pro/AGENTS.md). Frozen identities, -cache states and budgets are evidence contracts, not product runtime limits. - -### Fuser provenance and authorized-patch checks - -Additional owner authorization 2026-10-14: "you are allowed to modify fuser with -patch". The [receive-buffer decision](docs/issues/321/FUSER-RECEIVE-BUFFER-DECISION-20261014.md) -records the scope. Receive loops read into the `max_write + 4096` bytes -negotiated at INIT instead of fuser's 16 MiB + 4 KiB maximum. The delta is in -`read_buf.rs`, `session.rs` and `session/lifecycle.rs`, applied after the -lifecycle patch. `receive-buffer.patch` and `receive-buffer-provenance.json` -pin it, and the focused check verifies it. The earlier records stay unchanged. - -Additional owner authorization2026-10-08: the [scoped receive-loop lifecycle -extension](docs/issues/307/FUSER-LIFECYCLE-DECISION-20261008.md) may extend the -pinned fuser0.18.0 package beyond time.rs to establish loop entry/exit, retained -startup/join ownership and the proposed explicit lifecycle API. This narrowly -supersedes the timestamp-only file restriction below. Preserve the original -timestamp provenance unchanged; record and verify the lifecycle delta separately. -No other dependency change or general unsafe exception is authorized. Permission -does not establish implementation or native Ready/drain qualification. - -Latest owner direction2026-10-06: "use fuser 0.18.0 from crates io and apply patch". -This supersedes the earlier registry-only/no-patch ruling for this one correction. -Keep the dependency version exactly0.18.0; use the checked-in copy of its official -crates.io archive with only `src/time.rs` changed by the recorded upstream timestamp -fix and regression tests. Both owning workspace roots use the exact path/version -`[patch.crates-io]` entry. Do not edit shared Cargo registry packages, adopt a Git -dependency, or extend this exception to unrelated source/dependency changes. - -The original archive checksum, all85 published file hashes, exact diff and patched -time.rs hash are pinned in `patches/fuser-0.18.0/provenance.json` and checked by the -focused guard. A patched Cargo.lock entry has no registry checksum; the explicit -provenance record authenticates its modified bytes. See -[the authorized patch record](docs/issues/307/FUSER-REGISTRY-PATCH-20261006.md). -Native qualification and the complete S8 contract remain separate requirements. - -Subsequent owner direction2026-10-06: "docker verification is enough". Existing -native Docker proofs are accepted for verifying this fuser correction. Retain -Linux's fractional signed-minimum endpoint outcome as a platform limitation; -do not require QEMU or a custom-kernel campaign to verify the dependency fix. -This acceptance does not complete S8's product implementation or turn that -individual native FAIL into PASS. Continue the remaining S7–S9 work using Docker. - -Before a native fuser build, run the focused provenance check: - -```sh -python3 -B core/tools/check_fuser_integrity.py -``` - -For an installed registry source, also supply its archive, package directory and -checksum taken from its original registry lock or the pinned base-archive record -with `--archive`, `--package-directory` and `--locked-checksum`. This reads and -verifies package files without modifying -them. Run scoped self-tests when changing the check. It is not an aggregate -pre-push/CI wrapper or a timestamp-capability proof. Current evidence and the -historically rejected unmodified Git candidate are in -[the fuser verification record](docs/issues/307/FUSER-OFFICIAL-CANDIDATE-20261006.md). - -### Authorized Persistence seal file control - -Owner authorization 2026-10-07: "Approve the narrowly audited seal wrapper". -The system macOS SQLite enables persistent WAL and otherwise leaves empty -sidecars after checked close. Persistence uses `deny(unsafe_code)` with one -allowed module, `src/backend/sqlite/file_control.rs`, compiled on macOS only. -It sets and reads back `SQLITE_FCNTL_PERSIST_WAL` under sole seal ownership. -No other Persistence module may contain unsafe Rust; the guard and its tests -enforce the exact path. This does not authorize third-party patches, dependency -changes, manual sidecar deletion or other FFI. See the -[decision and diagnostic](docs/issues/307/SEAL-PERSIST-WAL-DECISION-20261007.md). +All product layers follow the +[production size and responsibility rules](../engine/AGENTS.md#production-file-size-and-responsibility) +and [verification rules](../engine/AGENTS.md#checks-and-completion). Build and +test through the selected worktree's registered private resources from the root +manifest. Build tests first with `--no-run`, then execute each selection under an +explicit wall timeout of at most 120 seconds. Preserve repository ARM64 flags, +locked dependencies, exact failure custody, the Disposable-only execution policy +and per-commit production LOC comparisons. Migrations retain cheap tests of +surviving behavior and delete tests that require retired scaffolding, with the +root guide's required behavior coverage and deletion record. + +For docs-only changes verify local links/anchors, status, claims and whitespace; +Rust/runtime checks do not apply. CI reports after a push and never gates it. diff --git a/core/README.md b/core/README.md index 2e47ec1be..539fe81b4 100644 --- a/core/README.md +++ b/core/README.md @@ -1,103 +1,20 @@ # LayerFS core -> **Status:** Current general guide. Crate list and production line counts are -> pinned to `664d02864e`. Implementation rules live in [AGENTS.md](AGENTS.md). - -`core/` is the LayerFS product: one Rust Cargo workspace with fourteen crates, -plus the JavaScript SDK's Node binding at [`../api/binding`](../api/binding). -It is the only product at HEAD. The v0.1.6 reference implementation that lived -under root `crates/` was retired on 2026-10-10 (R9c) and can be read at local tag -`reference-v0.1.6-final`; nothing in `core/` depends on it. - -## How the pieces fit - -- **One global Store.** All committed state (content objects, metadata and - history) lives in one SQLite Store file, opened with the Disposable profile - (WAL, `synchronous=OFF`). Project Init builds and seals it; it is then - installed on a volume the daemons share. Store Init, sealing and bounded - authenticated install live in `layerfs-project::store`; `layerfs-api` - re-exports their public names. See the - [composition boundary](docs/architecture/82-sdk-call-channel.md#project-store-composition-463). -- **Store calls run in the SDK's process.** The JavaScript SDK - ([`api`](../api/README.md)) calls `layerfs-api` through the Node - binding. Its fs, branch, project and operator methods run on - `layerfs-store-service` against the Store the SDK process opened directly. - This is the only route, and it is Linux only; elsewhere these calls fail - `Unsupported`. See [direct Store access](docs/issues/352/DIRECT_STORE.md). -- **Workspace calls go to the daemon.** `layerfs-daemon` runs inside a Sandbox - container that `layerfs-api` creates through `layerfs-sandbox` (Docker) and - reaches over an authenticated `layerfs-bridge` channel. It serves mount, exec, - Commit, status and unmount. -- **A Workspace is a full mutable view.** Mount binds a FUSE filesystem - (`layerfs-fuse`) over an immutable committed root (`layerfs-workspace`). Each - Workspace has its own overlay SQLite file (`layerfs-overlay`), copied from a - template at mount and deleted at unmount. Any process that can see the mount - uses it through ordinary filesystem calls; the daemon does not supervise - commands. -- **Commit publishes the Workspace's changes.** It captures what the Workspace - has published locally, builds new objects with the same content, storage and - persistence libraries Project Init uses, and publishes in one short step. - Writers take turns: heavy work happens first, and only the final publish holds - the single write lane. See the - [Store concurrency model](docs/architecture/83-store-concurrency-model.md). - -## Crates - -Production lines from `tools/production_loc.py` at `664d02864e`. Only the crate -directories are shown; the total is all of `core/crates/`. - -``` -core/crates/ [96,473] - layerfs-content/ [25,942] (canonical objects, file construction, bounded reads) - layerfs-storage/ [8,993] (content-addressed encoding and packs) - layerfs-history/ [990] (LayerStacks, Branches, Commits, Layers) - layerfs-persistence/ [8,398] (shared SQLite adapter and profiles) - layerfs-project/ [1,667] (namespace Init over the libraries above) - layerfs-telemetry/ [2,280] (parent/child timing trees) - layerfs-overlay/ [9,730] (one Workspace's disposable overlay database) - layerfs-workspace/ [8,991] (Workspace filesystem semantics) - layerfs-fuse/ [4,523] (kernel connection and request service) - layerfs-daemon/ [6,019] (Workspaces, Commit, the layerfs-daemon binary) - layerfs-store-service/ [9,821] (Store engine: reads, file changes, history) - layerfs-api/ [2,291] (SDK surface, one function per method) - layerfs-bridge/ [3,517] (authenticated bounded channels) - layerfs-sandbox/ [3,311] (container commands, streams, status) -``` - -The first six crates are the content, storage, history, persistence, Project Init -and telemetry libraries (cluster one; see the -[cluster-one handbook](../docs/general/cluster_one_handbook.md)). The rest are the -Workspace runtime, the Store engine and the SDK surface (cluster two; see the -[design index](docs/issues/303/README.md)). [Cargo.toml](Cargo.toml) decides what -is built. - -## Other folders - -- [`docs/architecture/`](docs/architecture/README.md): source-backed descriptions - of what the crates do, including the - [global SQLite Store](docs/architecture/84-global-sqlite-store.md) and the - [SDK call channel](docs/architecture/82-sdk-call-channel.md). -- [`docs/issues/`](docs/issues/): per-issue designs, fix records and evidence. - Closed issues are historical records. -- [`tools/`](tools/): the product boundary guard, the fuser integrity check and - telemetry report tools, each with its tests. -- `patches/` and `vendor/`: fuser 0.18.0 with the owner-authorized patches; see - [fuser provenance](AGENTS.md#fuser-provenance-and-authorized-patch-checks). - -## Checks - -Run from the repository root with the pinned toolchain. Build tests first with -`--no-run`, then run each test command under an explicit timeout of at most -120 s, selecting by package when the whole suite does not fit: - -```sh -cargo +1.85.1 test --manifest-path core/Cargo.toml --locked -p --all-targets --no-run -cargo +1.85.1 test --manifest-path core/Cargo.toml --locked -p --all-targets -cargo +1.85.1 clippy --manifest-path core/Cargo.toml --locked --all-targets -- -D warnings -cargo +1.85.1 fmt --manifest-path core/Cargo.toml --all -- --check -python3 -B core/tools/check_product_boundary.py -python3 -B -m unittest discover -s core/tools -p 'test_*.py' -``` - -There is no CI or aggregate pre-push gate. The full check contract, including -the aarch64 build flags, is in [AGENTS.md](AGENTS.md#checks-and-completion). +> **Status:** Current general guide. + +Core contains four crates: `layerfs-content`, `layerfs-history`, +`layerfs-storage` and `layerfs-telemetry`. They own canonical construction, +history contracts, content encoding/packing and observations. Core has no engine +or API dependencies, including tests, and no rusqlite dependency. + +Build membership is defined by the [root workspace manifest](../Cargo.toml). +See the [core guide](AGENTS.md), [engine guide](../engine/AGENTS.md), +[API guide](../api/AGENTS.md), [cluster-one handbook](../docs/general/cluster_one_handbook.md) +and [current operation contracts](docs/issues/303/README.md). + +The two workstreams remain unchanged. Store ownership, Project Store Init, +Workspace/Overlay, daemon/FUSE, Bridge and Sandbox composition live in engine; +SDK-facing Rust, binding and JavaScript code live in API. This source relocation +changes no public behavior, format or dependency version. The +[#463 implementation record](docs/issues/463/IMPLEMENTATION.md) records verification, +the retained FP-21 failure exception and branch coordination. diff --git a/core/crates/layerfs-content/README.md b/core/crates/layerfs-content/README.md index 1705a127e..200b68cf8 100644 --- a/core/crates/layerfs-content/README.md +++ b/core/crates/layerfs-content/README.md @@ -105,8 +105,9 @@ enabled or disabled changes no product work and no result. ## Checks ```sh -cargo +1.85.1 test --manifest-path core/Cargo.toml --locked -p layerfs-content --tests -cargo +1.96.0 clippy --manifest-path core/Cargo.toml --workspace --locked --all-targets -- -D warnings +cargo +1.85.1 test --manifest-path Cargo.toml --locked -p layerfs-content --tests --no-run +timeout 120 cargo +1.85.1 test --manifest-path Cargo.toml --locked -p layerfs-content --tests +cargo +1.85.1 clippy --manifest-path Cargo.toml --workspace --locked --all-targets -- -D warnings ``` External targets: `object_identity`, `file_complete`, `file_read`, `streaming`, diff --git a/core/crates/layerfs-storage/README.md b/core/crates/layerfs-storage/README.md index 3585a130f..1fb2ef0da 100644 --- a/core/crates/layerfs-storage/README.md +++ b/core/crates/layerfs-storage/README.md @@ -1,13 +1,14 @@ -> **Status:** Historical native-provider detail below; current C2 owns only the -> shared bounded save/read/encoding/pack flow. Persistence moved to -> [layerfs-persistence](../layerfs-persistence/README.md), with an atomic -> PackPersistence port and the new separately qualified WAL/FULL profile. Old -> MEMORY/OFF and private-save descriptions/receipts retain their historical scope. - # layerfs-storage (C2) -> **Status:** Implemented slice; FULL and PREFIX payload records, pooled physical -> metadata and an explicit multi-lane format matrix. +> **Status:** Current general guide; historical native-provider details below +> retain their original scope and receipts. + +Storage owns the shared bounded save/read, encoding and pack flow. Database +ownership belongs to [Persistence](../../../engine/crates/layerfs-persistence/README.md). +The original FULL/PREFIX slice and pooled physical metadata details below include +historical provider descriptions. MEMORY/OFF, WAL/FULL and private-save receipts +retain their original verdicts; current execution follows the root guide's +[Disposable-only profile](../../../AGENTS.md#active-persistence-profile--owner-direction-2026-10-07). Content-addressed physical storage. C2 accepts already-finalized canonical objects, performs exact CAS reuse, writes supported FULL records into framed @@ -140,7 +141,8 @@ destructor. ## Checks ```sh -cargo +1.85.1 test --manifest-path core/Cargo.toml --locked -p layerfs-storage --tests +cargo +1.85.1 test --manifest-path Cargo.toml --locked -p layerfs-storage --tests --no-run +timeout 120 cargo +1.85.1 test --manifest-path Cargo.toml --locked -p layerfs-storage --tests ``` The aggregate `tools/preflight.sh` gate is permanently retired (ledger L32) and runs diff --git a/core/crates/layerfs-telemetry/README.md b/core/crates/layerfs-telemetry/README.md index 4828bf2db..69bf69212 100644 --- a/core/crates/layerfs-telemetry/README.md +++ b/core/crates/layerfs-telemetry/README.md @@ -162,9 +162,9 @@ error. Flush is not crash durability. ## Examples ```sh -cargo run --manifest-path core/Cargo.toml --example timer_nested -cargo run --manifest-path core/Cargo.toml --example timer_composition -cargo run --manifest-path core/Cargo.toml --example timer_composition -- /tmp/run-1/timing.json +cargo run --manifest-path Cargo.toml --example timer_nested +cargo run --manifest-path Cargo.toml --example timer_composition +cargo run --manifest-path Cargo.toml --example timer_composition -- /tmp/run-1/timing.json ``` `timer_nested` shows injected parent/child scopes, an error that stops one branch @@ -195,10 +195,11 @@ it. ## Checks ```sh -python3 core/tools/check_product_boundary.py -cargo fmt --manifest-path core/Cargo.toml --all --check -cargo test --manifest-path core/Cargo.toml --workspace --locked -cargo clippy --manifest-path core/Cargo.toml --workspace --locked --all-targets -- -D warnings +python3 tools/check_product_boundary.py +cargo fmt --manifest-path Cargo.toml --all --check +cargo +1.85.1 test --manifest-path Cargo.toml --workspace --locked --no-run +timeout 120 cargo +1.85.1 test --manifest-path Cargo.toml --workspace --locked +cargo clippy --manifest-path Cargo.toml --workspace --locked --all-targets -- -D warnings ``` `tests/timer_json.rs` validates emitted JSON with Python's standard library diff --git a/core/docs/architecture/82-sdk-call-channel.md b/core/docs/architecture/82-sdk-call-channel.md index 949b91939..f8160b7db 100644 --- a/core/docs/architecture/82-sdk-call-channel.md +++ b/core/docs/architecture/82-sdk-call-channel.md @@ -290,15 +290,15 @@ through the Engine where the binding runs. See the ## Project Store composition (#463) Store Init, sealing and bounded authenticated installation live in -[`layerfs-project::store`](../../crates/layerfs-project/src/store/mod.rs). +[`layerfs-project::store`](../../../engine/crates/layerfs-project/src/store/mod.rs). The existing namespace constructor remains `layerfs_project::init_observed`; -[`store/init.rs`](../../crates/layerfs-project/src/store/init.rs) composes it +[`store/init.rs`](../../../engine/crates/layerfs-project/src/store/init.rs) composes it with Persistence creation, the first Branch, Init statistics and sole-owner seal. It requires Disposable explicitly and preserves original failure custody. Project depends on Bridge for the existing provisioning records and channel install protocol; it defines no second format or protocol. -[`layerfs-api::project`](../../crates/layerfs-api/src/project/mod.rs) and its +[`layerfs-api::project`](../../../api/layerfs-api/src/project/mod.rs) and its root retain the existing public names as re-exports. Its Control owner calls Project's `install_file` without changing correlation or quarantine. The [Node binding](../../../api/binding/src/project.rs) calls Project's Init once diff --git a/core/docs/issues/303/02-base-overlay.md b/core/docs/issues/303/02-base-overlay.md index 9041337ed..602f6ec27 100644 --- a/core/docs/issues/303/02-base-overlay.md +++ b/core/docs/issues/303/02-base-overlay.md @@ -60,7 +60,7 @@ object; it is not a field of `BranchSnapshot`, `core/crates/layerfs-history/src/records.rs:58-73`). The binding is replaced only by install. The base needs no lease: cluster one has no deletion path, so a root stays readable ([source-verified] pack rows are immutable by trigger, -`core/crates/layerfs-persistence/sql/sqlite/objects.sql:9-12`). The day a +`engine/crates/layerfs-persistence/sql/sqlite/objects.sql:9-12`). The day a collector exists, a lease becomes mandatory; that is recorded in [06 §7](06-cluster-one-integration.md#10-failure-boundaries). diff --git a/core/docs/issues/303/05-fuse-assessment.md b/core/docs/issues/303/05-fuse-assessment.md index 82f9c9dc4..f3fb0f286 100644 --- a/core/docs/issues/303/05-fuse-assessment.md +++ b/core/docs/issues/303/05-fuse-assessment.md @@ -28,7 +28,7 @@ dependencies, caches and output. No numerical result here qualifies that path. | Name | What it is | What it is not | | --- | --- | --- | -| Product on `main` | A private copy-on-write page store, one file per 4,096-byte page (`core/crates/layerfs-workspace/src/backing/active/pages.rs:130-131`), mounted with zero TTL and direct I/O (`core/crates/layerfs-fuse/src/adapter.rs:22`, `:228-234`) | Not a SQLite overlay. Never timed by #305 or #306 | +| Product on `main` | A private copy-on-write page store, one file per 4,096-byte page (`engine/crates/layerfs-workspace/src/backing/active/pages.rs:130-131`), mounted with zero TTL and direct I/O (`engine/crates/layerfs-fuse/src/adapter.rs:22`, `:228-234`) | Not a SQLite overlay. Never timed by #305 or #306 | | A1 | A throwaway ext4 passthrough daemon mounted with the product's profile values | Not the product: it shares none of the Workspace code | | A2 | The same passthrough with a 60 s entry/attribute lifetime, `FOPEN_KEEP_CACHE` and `fsync` accepted as a no-op | No overlay, no generations, no capture, no Commit, no base acquisition, no cluster one work, no invalidation of any kind | | B | A throwaway four-table SQLite prototype over a local directory, under the A1 profile | Not the design in this set. Its only non-trivial cell FAILED | @@ -59,7 +59,7 @@ Experiment source is `core/experiment/real-tree/src/` on the same branch. - A1 and A2 differ in three coupled settings (lifetime, cache mode, `fsync`). No arm separates them. - A2 runs as uid/gid 1000 with `allow_other`; the product mounts owner-only as - uid 0 (`core/crates/layerfs-fuse/src/mount.rs:209`, `:400-427`). + uid 0 (`engine/crates/layerfs-fuse/src/mount.rs:209`, `:400-427`). ### 1.2 Owner decisions on record diff --git a/core/docs/issues/303/07-implementation-validation.md b/core/docs/issues/303/07-implementation-validation.md index f511d51cd..9fcf7de86 100644 --- a/core/docs/issues/303/07-implementation-validation.md +++ b/core/docs/issues/303/07-implementation-validation.md @@ -53,9 +53,9 @@ historical baseline pins, receipts and verdicts retain their original scope. - `main` at `f96d97651be5299f153ccde2bc8d921dd58807ad`. - The cluster two crates (`layerfs-workspace`, `-fuse`, `-daemon`, `-bridge`, `-sandbox`, both `layerfs-api` packages) and `layerfs-server` are in `exclude` - in `core/Cargo.toml:19-28`. They are byte-identical to `7edddbdb8`, have no lock + in `Cargo.toml:19-28`. They are byte-identical to `7edddbdb8`, have no lock entries, and are not built or tested by the prescribed - `--manifest-path core/Cargo.toml` commands. + `--manifest-path Cargo.toml` commands. - `layerfs-server` and the SDK import `layerfs_storage::Store` and `layerfs_history::sqlite`, which cluster one no longer exports. This comes from reading imports and exports; nothing was compiled. @@ -146,7 +146,7 @@ identities. | Sandbox integration | Running Linux ARM64 Docker backend; checked client/server version 29.5.2 | Actual daemon, SQLite overlay, Linux FUSE mounts and ordinary Bash execution | | Host provisioning/control | macOS Project Init/seal/install, then control-only | Explicit Disposable Store; no installed Store handle or object/Save/history data service | | Sandbox runtime | Linux sandbox with a daemon initialized before Workspace readiness | Direct shared Store and one local Overlay per daemon; multiple Workspaces; ordinary runtime owns processes/streams | -| Build outputs | Worktree-owned `core/target/`; distinct owned Linux target such as `core/target/cluster2-linux/` | Reuse matching build seals; no target/cache borrowed from another worktree | +| Build outputs | Worktree-owned `target/`; distinct owned Linux target such as `target/cluster2-linux/` | Reuse matching build seals; no target/cache borrowed from another worktree | Docker availability does not prove mounted FUSE readiness or the locked Linux toolchain. S0 still establishes the real image/build configuration, `/dev/fuse` diff --git a/core/docs/issues/303/fuse.md b/core/docs/issues/303/fuse.md index b812be355..310fe3dc3 100644 --- a/core/docs/issues/303/fuse.md +++ b/core/docs/issues/303/fuse.md @@ -100,9 +100,9 @@ proof remain required; all 10070 symlinks stay in scope. | xattrs/ownership | Unsupported | Explicit supported-format boundary, never hidden omission | | Contention | Reply permits can return EBUSY | No contention EBUSY; park waiters without holding workers | -Current sources: [adapter](../../../crates/layerfs-fuse/src/adapter.rs), -[mount](../../../crates/layerfs-fuse/src/mount.rs), -[replies](../../../crates/layerfs-fuse/src/replies.rs). These crates are excluded +Baseline sources at `f96d97651`: [adapter](https://github.com/Ephemeral-AI-Lab/layerfs/blob/f96d97651be5299f153ccde2bc8d921dd58807ad/core/crates/layerfs-fuse/src/adapter.rs), +[mount](https://github.com/Ephemeral-AI-Lab/layerfs/blob/f96d97651be5299f153ccde2bc8d921dd58807ad/core/crates/layerfs-fuse/src/mount.rs), +[replies](https://github.com/Ephemeral-AI-Lab/layerfs/blob/f96d97651be5299f153ccde2bc8d921dd58807ad/core/crates/layerfs-fuse/src/replies.rs). At that pin these crates were excluded from the active core workspace; their presence is not a built replacement. Portable metadata's ctime=mtime behavior is an explicit compatibility decision, not full POSIX metadata fidelity. diff --git a/core/docs/issues/463/IMPLEMENTATION.md b/core/docs/issues/463/IMPLEMENTATION.md index cb1ae0f07..6f987e808 100644 --- a/core/docs/issues/463/IMPLEMENTATION.md +++ b/core/docs/issues/463/IMPLEMENTATION.md @@ -1,7 +1,8 @@ # #463 implementation record -> **Status:** In progress; source/check record for the layer split. Not a release -> contract or performance qualification. Steps 3 and 4 have not started. +> **Status:** Current implementation record; layer split complete with the +> owner-authorized FP-21 verification exception. Not a release contract or +> performance qualification. ## Owner decisions @@ -71,7 +72,7 @@ Production LOC: 102158 -> 102158 (delta 0), same subtotals as the prerequisite. ## Step 2a — Project Store composition Commit `0f442d5bb7`: the three implementation files move to -[`layerfs-project::store`](../../../crates/layerfs-project/src/store/mod.rs). +[`layerfs-project::store`](../../../../engine/crates/layerfs-project/src/store/mod.rs). Their bodies remain unchanged. Project gains the approved Bridge and Persistence production edges; the Node binding calls this Project Init directly. `layerfs-api` retains its public names as re-exports and its Control owner calls @@ -121,6 +122,8 @@ using the existing physical scopes before relocation. ## Step 2b — daemon test ownership +Commit `3cae8b1a1e`. + Eight test targets move from daemon to API: `mount_control`, `kernel_mount_routes`, `kernel_application`, `observed_application`, `r5_1_actual_daemon_commit`, `merge_report`, `concurrent_commits` and @@ -152,6 +155,86 @@ Production LOC: 102162 -> 102162 (delta 0). Core 96794; API 5368, using the physical scopes before relocation. +## Step 3 — relocation + +Commit `ce2c0eb411` moves nine engine crates and the Rust API, the workspace +manifest/lock, nextest configuration, tools and authorized fuser package/patch +records to their selected roots. The four core crates remain in place. Relative +manifest paths, cross-crate test includes, native scripts, worktree resources, +CI paths and the LOC counter follow the new layout. The redundant old core +counter is deleted after verifying no live caller outside historical docs. + +The exact comparison checks all 954 production files: identical body bytes and +per-file LOC, with 572 files relocated. Cargo metadata preserves all fifteen +packages, their versions/features and every first-party edge, kind, target, +alias and dependency feature. The lockfile and third-party source bytes remain +unchanged. Every moved file is recognized with `git diff -M20%`; the two path +manifests' extensive rewrites fall below Git's default similarity threshold. +This is a source relocation, not a simplification. + +The full root all-target no-run build and warning-denying Clippy pass for all +fifteen packages. Linux executable verification records 346 passed selections, +one retained FP-21 failure and none unrun, under individual 100-second ceilings. +The fixture-seal guard initially failed because it still required +`core/Cargo.toml`; this additional live path assumption was not in the spec's +initial inventory. Its repaired case, +`no_product_source_can_reseal_during_an_ordinary_test_run`, finds the root +manifest and scans all relocated first-party product/tooling roots. All original +assertions remain; the five unchanged cases reuse their initial passing proof. +The original failure receipt is retained. No tests are deleted in this step. + +Also passed: literal native build script; paired daemon/addon SDK bundle build; +sealed SDK `init_refusals.mjs` under a 90-second ceiling; full boundary guard +(954 inputs); fuser provenance (33 manifests/locks/configurations); all 154 +combined Python tool tests under 120 seconds; Rust formatting, Ruff 0.17.2 +formatting and whitespace. The selected Linux build/runtime images and private +volumes retain their registered identities. Only this worktree's target record +was updated and prepared; no other worktree's record was migrated. + +Production LOC: 102162 -> 102162 (delta 0), using the new counter on both exact +parent and staged snapshots. Per-crate totals are identical. Layer subtotals: +core 38241; engine 56640; API 7281. No upward guard exception remains. The +runtime FP-21 exception remains explicitly separate from the passing checks. + +## CI timing record + +Commit `ef4c26b02b` records the existing Persistence `writer_admission` target's +9.74-second Linux functional run in SLOW, as repository policy requires. It is +separate from the path relocation and changes only CI selection data. All six +CI-selection/executable self-tests pass under a 120-second ceiling, as do Ruff +formatting and whitespace. Rust/runtime checks do not apply to this data-only +change; the completed relocation proofs remain applicable. No tests deleted. + +Production LOC: 102162 -> 102162 (delta 0); core 38241, engine 56640, API 7281. + +## Step 4 — documentation + +The documentation commit containing this record splits the implementation guide +into core, engine and API ownership. Common source-size, verification, profile, +execution and failure rules remain binding across all product layers. Engine +owns daemon/FUSE, the authorized fuser patches, Persistence seal control and +Project Store composition, including the approved Bridge/Persistence edges. + +Maintained guides, crate READMEs, current design navigation and native proof +instructions follow the new paths. All six named SDK skill references were +checked: five needed edits; LWW still points to the surviving core Content +source. The #337 receipt path retains its historical source identity. Archived +queue-scheduling documentation and dated records are unchanged. Links to retired +source in maintained guides now use their verified immutable source commits; +claims and original qualification limits are preserved. + +Local links/anchors, status banners, command paths and whitespace are checked. +Rust/runtime checks do not apply to this docs-only commit. Production LOC stays +102162 -> 102162 (delta 0), with the same layer subtotals. + +## External consumers + +No outside repository is changed. layerfs-benchmark's `common/lib.sh` still +hard-codes `core/target/fs-bench-bin`; fs-bench-pro remains frozen and unrun. +dsh-layerfs and magpie-layerfs retain their pins; their next pin bumps must build +from the new root manifest. No follow-up issue, push, PR or merge is requested. + + ## Relocation coordination All five branches named in the spec still have unmerged `core/crates` changes: @@ -160,8 +243,8 @@ All five branches named in the spec still have unmerged `core/crates` changes: #445, #418 and #419; #424 remains open under its remote fix branch. The local Claude worktree also remains registered. No branch is rebased or edited by this task. After this inventory was reported, the owner confirmed: “Their owners are -ready to rebase; relocate now.” Step 3 is authorized after step 2 verification; -these branches will need rebasing, and this task does not edit them. +ready to rebase; relocate now.” Step 3 proceeded after step 2 verification; +these branches need rebasing, and this task does not edit them. A fresh read of all open PR file lists also finds `core/crates` edits in: @@ -184,9 +267,11 @@ This is coordination inventory only; their work is not edited or merged here. ## Counting and retained evidence -Each LOC comparison uses the unchanged root `tools/production_loc.py --json` -from exact parent/staged snapshots, excluding comments and inline tests and -including shipped SQL and the JavaScript API. Staged tree hashes are checked +The prerequisite and steps 1/2 use their unchanged root +`tools/production_loc.py --json`. Step 3 uses the new counter on both layouts, +classifying crates by name; later commits use that same counter unchanged. +All comparisons use exact parent/staged snapshots, exclude comments and inline +tests and include shipped SQL and the JavaScript API. Staged tree hashes are checked against the resulting committed trees. Counts are source-size comparisons only. reference absent (retired R9c; last counted 65,417 at tree 498dd1917812). @@ -194,5 +279,46 @@ reference absent (retired R9c; last counted 65,417 at tree 498dd1917812). Build/test logs and exact LOC receipts are retained under the registration's `builds/` and `artifacts/` directories outside Git. No benchmark is run. Durable execution is NOT_RUN — disabled by the owner until explicit -reauthorization. No caches have yet been released; active private targets remain -warm until handoff. +reauthorization. Cache release and final disk evidence are recorded below. + + +## Cache/evidence handoff and disk + +The exact cache releases are exported in `artifacts/cache-release-export.json` +and the protected derived scope under registration +`issue463-layer-split-0e1ca01332b4`. The cleanup plan/apply procedure removed +this assignment's private target and Cargo dependency volumes: +`lfs-dev-issue463-layer-split-0e1ca01332b4-target` and +`lfs-dev-issue463-layer-split-0e1ca01332b4-cargo`. The repaired fixture-seal +failure's verified-empty scratch volume was also removed. The old host +`core/target` and new host `target` directories contained no build cache and +were removed only after verifying they were empty. Other worktrees, their warm +caches and resource records are untouched. Prepare this registration before a +future build; sealed SDK bundles remain available outside the caches. + +Four completed stopped containers were archived and retired. The original +cleanup attempt retained three after Docker reordered its Mounts array between +plan and apply. Inspection confirmed equal full identities after sorting that +array; a task-local wrapper canonicalized its order without dropping identity +fields or changing repository cleanup code. The original partial report and +subsequent successful report are retained. No active container was retired. + +The original FP-21 output, FAIL receipt, configuration and logs remain retained. +Its original executable was archived and verified byte-exactly before the cache +was released: SHA-256 +`a3f8aed65b262fe920c9fd34bdf0ca96cd0805d39d5cb3991b0e060d5bba0dba`. +Recovery tree `f3dcbed8566d0f8311949d74fcfcb4b702ff7de5` is retained at +`refs/cleanup/20261026T190651Z-21eeb1b8bb82/197f54e38b82bd8d6efa`. +Its original scratch volume +`lfs-dev-issue463-layer-split-0e1ca01332b4-c4033190aba64b258223c701b3e1175c-tmp` +remains protected until its owner resolves the staging assumption. Archival and +cache disposal do not change the original FAIL or authorize a replay. + +Settled host free space at 2026-10-26T19:12:32.054565+00:00: 367572975616 bytes +(367.57 GB). Docker guest free: 95400038400 bytes +(88.85 GiB). The cache cleanup +initially observed only 765952 net host bytes; after delayed +reclamation the observed net was 60979404800 bytes. These are +free-byte observations including concurrent activity, not allocation estimates. +Host space stayed above the 100 GB threshold; no 300 GB recovery episode was +triggered. Cleanup reports record no lost pins. diff --git a/docs/general/benchmark_instruction.md b/docs/general/benchmark_instruction.md index fa7886cde..d8ef4dd31 100644 --- a/docs/general/benchmark_instruction.md +++ b/docs/general/benchmark_instruction.md @@ -273,7 +273,7 @@ the edit, and the sample only confirms it. ```bash RX_ONLY=costs,compound,transactions,native_visit_fence,native_visit_cost,job_cost \ - python3 -B core/target/rx-suite.py host layerfs-overlay layerfs-workspace layerfs-daemon + python3 -B target/rx-suite.py host layerfs-overlay layerfs-workspace layerfs-daemon ``` Restage a count test with the true new number in the same commit; never @@ -567,16 +567,16 @@ concurrent clients, Commit, or a cell that did not run. ## Helpers -`core/target/r7-summary.py ` prints the outcome, request, job, -statement, Store and storage rows; `core/target/r7-statements.py +`target/r7-summary.py ` prints the outcome, request, job, +statement, Store and storage rows; `target/r7-statements.py ` prints per-family statements, executions, VM steps and time. -`core/target/rx-suite.py host|linux ...` builds once +`target/rx-suite.py host|linux ...` builds once and runs each test binary once under its own wall limit; `RX_ONLY=a,b,c` restricts both the build and the run to the named integration-test binaries. -`core/target/r7-iterate-all.sh [cells]` samples the -named cells from one build. All are in the git-ignored `core/target` +`target/r7-iterate-all.sh [cells]` samples the +named cells from one build. All are in the git-ignored `target` directory and are lost if it is cleaned. The array positions they decode are pinned to the product's -diagnostics source (`core/crates/layerfs-overlay/src/diagnostics/metrics.rs` -and the request accounting in `core/crates/layerfs-fuse`); a changed family or +diagnostics source (`engine/crates/layerfs-overlay/src/diagnostics/metrics.rs` +and the request accounting in `engine/crates/layerfs-fuse`); a changed family or opcode list must be updated in the helper, which warns when the lengths differ. diff --git a/docs/general/cas_cdc_deltaencoding_handbook.md b/docs/general/cas_cdc_deltaencoding_handbook.md index 876183074..8fdc43bb4 100644 --- a/docs/general/cas_cdc_deltaencoding_handbook.md +++ b/docs/general/cas_cdc_deltaencoding_handbook.md @@ -337,7 +337,7 @@ chunk the base payload covering its byte range: | Producer | Base offered | Source | | --- | --- | --- | | Localized edit of a file the base holds (#352 F-005) | the same file's base mapping, through the edit's `Aligner` | [edit apply](../../core/crates/layerfs-content/src/file/edit/apply.rs) | -| Workspace Commit of a fresh file that a rename put in place of another (#352 F-063) | the replaced file, through the same `Aligner`, via `construct_runs_with_predecessor` | [run constructor](../../core/crates/layerfs-content/src/file/construction/runs.rs), [captured file](../../core/crates/layerfs-workspace/src/construction/captured/owner.rs) | +| Workspace Commit of a fresh file that a rename put in place of another (#352 F-063) | the replaced file, through the same `Aligner`, via `construct_runs_with_predecessor` | [run constructor](../../core/crates/layerfs-content/src/file/construction/runs.rs), [captured file](../../engine/crates/layerfs-workspace/src/construction/captured/owner.rs) | | `construct_bytes_with_predecessor` with a caller's base | the supplied root, positionally | [byte constructor](../../core/crates/layerfs-content/src/file/construction/bytes.rs) | The F-063 route exists because git, editors and package managers save by diff --git a/docs/general/cleanup.md b/docs/general/cleanup.md index 351e55328..342d569c1 100644 --- a/docs/general/cleanup.md +++ b/docs/general/cleanup.md @@ -370,8 +370,8 @@ or the user authorization recorded by discovery. Example selections: "actions": [ { "kind": "cargo-cache", - "path": "/absolute/path/to/completed-worktree/core/target/debug", - "target_root": "/absolute/path/to/completed-worktree/core/target", + "path": "/absolute/path/to/completed-worktree/target/debug", + "target_root": "/absolute/path/to/completed-worktree/target", "owner": "completed assignment owner", "reason": "assignment handed off; cache released", "released": true diff --git a/docs/general/cluster_one_handbook.md b/docs/general/cluster_one_handbook.md index 36f2a569a..c9849ba7d 100644 --- a/docs/general/cluster_one_handbook.md +++ b/docs/general/cluster_one_handbook.md @@ -109,7 +109,7 @@ been deleted; `layerfs-metadata` is also absent. The combined `layerfs-persistence` crate is the active provider. Historical plans describing those backends must not be used as instructions for the current implementation. -Sources: [workspace](../../core/Cargo.toml), +Sources: [workspace](../../Cargo.toml), [content public surface](../../core/crates/layerfs-content/src/lib.rs), [storage public surface](../../core/crates/layerfs-storage/src/lib.rs), [history contract](../../core/crates/layerfs-history/src/contract/catalog.rs), @@ -190,9 +190,9 @@ let construction = storage.policy().construction(); let capacities = construction.capacities(); ``` -Source: [configuration](../../core/crates/layerfs-persistence/src/store/config.rs), -[open/create](../../core/crates/layerfs-persistence/src/store/open.rs), -[handles](../../core/crates/layerfs-persistence/src/store/handles.rs), +Source: [configuration](../../engine/crates/layerfs-persistence/src/store/config.rs), +[open/create](../../engine/crates/layerfs-persistence/src/store/open.rs), +[handles](../../engine/crates/layerfs-persistence/src/store/handles.rs), [storage](../../core/crates/layerfs-storage/src/store/handle.rs). ### 3.2 Construction, read, and filesystem APIs @@ -439,7 +439,7 @@ genesis LayerStack, not just file payload storage. The deadline is shared with workers; it is not a rollback boundary. Seal is a separate consuming handle lifecycle operation, not a substitute for either Save finish. -Source: [Init API](../../core/crates/layerfs-project/src/import/init.rs). +Source: [Init API](../../engine/crates/layerfs-project/src/import/init.rs). Directory construction uses bounded `Acquisition::bindings` windows containing name, position and canonical identity; inode and alias validation retain full @@ -559,8 +559,8 @@ must still provide stable input: those checks are not a general snapshot service Ordering scratch for filesystem construction does not remove the retained scan collections. A fully file-count-bounded importer remains additional work. -Sources: [worker scan](../../core/crates/layerfs-project/src/import/scan.rs), -[batch/channel](../../core/crates/layerfs-project/src/import/batch.rs), +Sources: [worker scan](../../engine/crates/layerfs-project/src/import/scan.rs), +[batch/channel](../../engine/crates/layerfs-project/src/import/batch.rs), [storage bounds](../../core/crates/layerfs-storage/src/store/policy.rs), [construction](../../core/crates/layerfs-content/src/file/construction/bytes.rs). diff --git a/docs/general/optimization-guide.md b/docs/general/optimization-guide.md index 2d1cb0193..f91c14371 100644 --- a/docs/general/optimization-guide.md +++ b/docs/general/optimization-guide.md @@ -257,8 +257,8 @@ are not automatically a profile of one Workspace or phase. The current global provider already records actual VM steps and inclusive statement/transaction/BLOB observations in -[SqlWork](../../core/crates/layerfs-persistence/src/backend/sqlite/connection.rs) -and its [query execution](../../core/crates/layerfs-persistence/src/backend/sqlite/query.rs). +[SqlWork](../../engine/crates/layerfs-persistence/src/backend/sqlite/connection.rs) +and its [query execution](../../engine/crates/layerfs-persistence/src/backend/sqlite/query.rs). Confirm observation coverage and aggregation before using it for a statement claim. Global-provider profiling does not automatically profile the daemon's separate overlay engine. diff --git a/docs/general/optimization-handbook.md b/docs/general/optimization-handbook.md index 14be52701..421a0bbc4 100644 --- a/docs/general/optimization-handbook.md +++ b/docs/general/optimization-handbook.md @@ -76,23 +76,23 @@ Start here. None of these needs new product code. | What it counts | Type and fields | Source | How to read it | | --- | --- | --- | --- | -| Requests per opcode for one connection | `OpcodeWork`: `opcodes[]`, `handoffs`, `inline`, `refused`, `terminal`, `unadmitted`, `forget_units` | [`request/accounting.rs`](../../core/crates/layerfs-fuse/src/request/accounting.rs) | In the drain receipt after unmount | -| A mount's live request state | `NativeWork`: `received`, `admitted`, `queued`, `running`, `parked`, `retained`, `completed`, loop counts | [`control_native.rs`](../../core/crates/layerfs-bridge/src/control_native.rs) | Control Status while mounted; the unmount receipt afterwards | -| The dispatcher as a whole | `DispatchWork`: workers, mounts, `queued`, `running`, `parked`, `retained` | [`layerfs-fuse/src/dispatch`](../../core/crates/layerfs-fuse/src/dispatch) | Through the native serving assembly | -| Owner jobs per class | `OwnerWork`: `admitted`, `completed[6]`, `queue_wait_ns[6]`, `service_ns[6]`, `outstanding`, `queued`, `peak_queued`, maintenance jobs and rows | [`overlay/queue.rs`](../../core/crates/layerfs-daemon/src/overlay/queue.rs) | The six classes are Read, Mutation, Capture, Lifecycle, OperationRecord and Source ([`commands.rs`](../../core/crates/layerfs-daemon/src/overlay/commands.rs)) | -| SQL work per statement family | `StatementWork`: `executions`, `rows_returned`, `rows_changed`, `vm_steps`, `fullscan_steps`, `sorts`, `autoindex_rows`, `reprepares`, bytes, `elapsed_ns` | [`diagnostics/metrics.rs`](../../core/crates/layerfs-overlay/src/diagnostics/metrics.rs) | Fourteen families (`StatementKind`); foreground and maintenance are separate in `OwnerWork`; each job's completion carries its own receipt | -| Query plans of the overlay | `explain_*` functions per family | [`layerfs-overlay/src`](../../core/crates/layerfs-overlay/src) | Reached through owner commands that return plans | -| Stored rows and pages | `StoredCounts` | [`database/accounting.rs`](../../core/crates/layerfs-overlay/src/database/accounting.rs) | Plateau and leak checks | -| Base demands on the Store | `StoreWork`: `object_batches`, `object_ids`, `length_batches`, `length_ids`, `serial_reservations` | [`store/open.rs`](../../core/crates/layerfs-daemon/src/store/open.rs) | A warm phase must show zero object demands | -| Store reader pool | `ReadServiceWork`: `readers`, `quarantined`, `waiting`, `leased`, `peak_outstanding`, `grants`, `queue_wait_ns`, `maximum_queue_wait_ns` | [`store/read_service.rs`](../../core/crates/layerfs-daemon/src/store/read_service.rs) | Reader contention and quarantine | -| Namespace construction in a Commit | `CapturedNamespaceWork`: rows, pages, `parent_points`, `base_lookups`, headers, values, `files_constructed`, record jobs | [`construction/outcome.rs`](../../core/crates/layerfs-workspace/src/construction/outcome.rs) | In the Commit success or failure | +| Requests per opcode for one connection | `OpcodeWork`: `opcodes[]`, `handoffs`, `inline`, `refused`, `terminal`, `unadmitted`, `forget_units` | [`request/accounting.rs`](../../engine/crates/layerfs-fuse/src/request/accounting.rs) | In the drain receipt after unmount | +| A mount's live request state | `NativeWork`: `received`, `admitted`, `queued`, `running`, `parked`, `retained`, `completed`, loop counts | [`control_native.rs`](https://github.com/Ephemeral-AI-Lab/layerfs/blob/2b4dc28a6d93aace6405a6baa5271e344b1cf5c2/core/crates/layerfs-bridge/src/control_native.rs) | Control Status while mounted; the unmount receipt afterwards | +| The dispatcher as a whole | `DispatchWork`: workers, mounts, `queued`, `running`, `parked`, `retained` | [`layerfs-fuse/src/dispatch`](../../engine/crates/layerfs-fuse/src/dispatch) | Through the native serving assembly | +| Owner jobs per class | `OwnerWork`: `admitted`, `completed[6]`, `queue_wait_ns[6]`, `service_ns[6]`, `outstanding`, `queued`, `peak_queued`, maintenance jobs and rows | [`overlay/queue.rs`](https://github.com/Ephemeral-AI-Lab/layerfs/blob/2b4dc28a6d93aace6405a6baa5271e344b1cf5c2/core/crates/layerfs-daemon/src/overlay/queue.rs) | The six classes are Read, Mutation, Capture, Lifecycle, OperationRecord and Source ([`commands.rs`](https://github.com/Ephemeral-AI-Lab/layerfs/blob/2b4dc28a6d93aace6405a6baa5271e344b1cf5c2/core/crates/layerfs-daemon/src/overlay/commands.rs)) | +| SQL work per statement family | `StatementWork`: `executions`, `rows_returned`, `rows_changed`, `vm_steps`, `fullscan_steps`, `sorts`, `autoindex_rows`, `reprepares`, bytes, `elapsed_ns` | [`diagnostics/metrics.rs`](../../engine/crates/layerfs-overlay/src/diagnostics/metrics.rs) | Fourteen families (`StatementKind`); foreground and maintenance are separate in `OwnerWork`; each job's completion carries its own receipt | +| Query plans of the overlay | `explain_*` functions per family | [`layerfs-overlay/src`](../../engine/crates/layerfs-overlay/src) | Reached through owner commands that return plans | +| Stored rows and pages | `StoredCounts` | [`database/accounting.rs`](../../engine/crates/layerfs-overlay/src/database/accounting.rs) | Plateau and leak checks | +| Base demands on the Store | `StoreWork`: `object_batches`, `object_ids`, `length_batches`, `length_ids`, `serial_reservations` | [`store/open.rs`](https://github.com/Ephemeral-AI-Lab/layerfs/blob/2b4dc28a6d93aace6405a6baa5271e344b1cf5c2/core/crates/layerfs-daemon/src/store/open.rs) | A warm phase must show zero object demands | +| Store reader pool | `ReadServiceWork`: `readers`, `quarantined`, `waiting`, `leased`, `peak_outstanding`, `grants`, `queue_wait_ns`, `maximum_queue_wait_ns` | [`store/read_service.rs`](https://github.com/Ephemeral-AI-Lab/layerfs/blob/2b4dc28a6d93aace6405a6baa5271e344b1cf5c2/core/crates/layerfs-daemon/src/store/read_service.rs) | Reader contention and quarantine | +| Namespace construction in a Commit | `CapturedNamespaceWork`: rows, pages, `parent_points`, `base_lookups`, headers, values, `files_constructed`, record jobs | [`construction/outcome.rs`](../../engine/crates/layerfs-workspace/src/construction/outcome.rs) | In the Commit success or failure | | Storage read and save path | `Diagnostics`: locate, pack reads and selections, reservations, publish, payload reads, locator and pack cache hits and evictions | [`read/counters.rs`](../../core/crates/layerfs-storage/src/read/counters.rs) | In the Commit outcome | -| Global Store SQL | `SqlWork`: statements, actual VM steps, transactions | [`sqlite/connection.rs`](../../core/crates/layerfs-persistence/src/backend/sqlite/connection.rs) | Separate from the overlay engine | +| Global Store SQL | `SqlWork`: statements, actual VM steps, transactions | [`sqlite/connection.rs`](../../engine/crates/layerfs-persistence/src/backend/sqlite/connection.rs) | Separate from the overlay engine | | Kernel queue of one connection | `waiting`, `max_background`, `congestion_threshold` | the mount's own entry under the fusectl filesystem | Read only your own connection. Nothing writes there except the product's own abort | Existing count tests show the pattern for asserting work instead of time: `job_cost`, `startup_cost`, `e2_startup_receipts` and `product_commit_cost` in -[`layerfs-daemon/tests`](../../core/crates/layerfs-daemon/tests). +[`layerfs-daemon/tests`](../../engine/crates/layerfs-daemon/tests). External observers that need no product change: a syscall count of the command on native ext4, the mount table, and per-process state under `/proc`. If a @@ -188,8 +188,8 @@ The cheapest request is one the kernel never sends. writeback to cut requests. Do not treat lifetime expiry as correctness. - **Current profile.** 60 s entry and attribute lifetime, cached reads, writeback off, `default_permissions`, background depth 1 - ([`reply.rs`](../../core/crates/layerfs-fuse/src/request/reply.rs), - [`profile.rs`](../../core/crates/layerfs-fuse/src/mount/profile.rs)). + ([`reply.rs`](../../engine/crates/layerfs-fuse/src/request/reply.rs), + [`profile.rs`](../../engine/crates/layerfs-fuse/src/mount/profile.rs)). Changing it is an owner decision. - **Proofs.** `native_coherence`, `native_mutation`, `native_mount`, `mounted_install`. diff --git a/docs/general/parallel-worktrees.md b/docs/general/parallel-worktrees.md index f7c4753b9..575d532b5 100644 --- a/docs/general/parallel-worktrees.md +++ b/docs/general/parallel-worktrees.md @@ -38,9 +38,9 @@ registered checkout without copying scripts into it or merging branches first. | Resource | Owner and placement | | --- | --- | | Source | Registered checkout; mounted at `/work` read-only during Linux builds | -| macOS Cargo target | That checkout's `core/target` | +| macOS Cargo target | That checkout's `target` | | macOS Cargo home | Private directory in its registration state | -| Linux Cargo target | Labelled private Docker volume at `/work/core/target` | +| Linux Cargo target | Labelled private Docker volume at `/work/target` | | Linux Cargo home | Separate labelled private Docker volume at `/cargo-home` | | Toolchain/images | Pinned toolchain and shared immutable installed images | | E2E artifacts | Unique sealed bundle containing daemon, addon, SDK runtime/operator/test files, the `layerfs` command (`api/agent/cli/src`, `api/agent/cli/test`), hashes and source identity | @@ -95,7 +95,7 @@ The Linux target mount stays inside `/work`, which also satisfies the existing The standalone `build:native` script remains available; the isolated launcher publishes the daemon and addon together rather than overwriting a live addon. -Builds start at the checkout root with `--manifest-path core/Cargo.toml`, preserving +Builds start at the checkout root with `--manifest-path Cargo.toml`, preserving the root ARM64 Cargo profile. They reject inherited Rust flag/target/compiler overrides that would bypass it. Source files, the lockfile, root configuration, SDK runtime, operator and test files, and the `layerfs` command's source and @@ -191,3 +191,18 @@ only with the explicit handoff release. The cleanup script independently recheck active processes and all container consumers before any deletion. Ordinary cleanup can omit the 300 GB target when no low-space episode is active. The launcher does not remove checkouts or frozen evidence, and never runs a global Docker prune. + + +## Existing registrations after the layer split + +After rebasing across #463, close build/test owners in your selected worktree. +For a registration made before the move, retain its original `resources.json` +and update only that registration's `macos_target` from the selected checkout's +`core/target` to its `target` directory. The Linux volume names and Cargo homes +remain private and unchanged; the launcher now mounts the target at `/work/target`. +Run `prepare` again for each platform you use. Registration verifies exact inputs +and does not silently rewrite an older record; `prepare` reads the selected +record, so its target path must be updated first. Never scan or migrate another +worktree's records. Keep an active cache warm and release the old cache through +the cleanup procedure at handoff; retain records, sealed bundles and failed-run +evidence. diff --git a/docs/general/sandbox-cache-design.md b/docs/general/sandbox-cache-design.md index 556730670..a440784a2 100644 --- a/docs/general/sandbox-cache-design.md +++ b/docs/general/sandbox-cache-design.md @@ -84,31 +84,31 @@ one daemon (complete process/bootstrap integration still in progress) The relevant production boundaries are: -- [`workspace.rs`](../../core/crates/layerfs-workspace/src/workspace/state.rs): +- [`workspace.rs`](../../engine/crates/layerfs-workspace/src/workspace/state.rs): `Workspace::open` accepts `Arc`, a filesystem root, allocation scope and incarnation, then binds a separate overlay route. -- [`base.rs`](../../core/crates/layerfs-workspace/src/base/view.rs): `BaseView` retains +- [`base.rs`](../../engine/crates/layerfs-workspace/src/base/view.rs): `BaseView` retains that root and shared client; lookup, listing and file reads use public cluster-one content APIs. Root binding reads the root without enumerating the whole namespace or materializing all file payloads. -- [`client.rs`](../../core/crates/layerfs-workspace/src/base/client.rs): +- [`client.rs`](../../engine/crates/layerfs-workspace/src/base/client.rs): `CanonicalClient` checks demand cardinality, object identities and processing windows, and releases the cache lock before upstream acquisition. -- [`cache.rs`](../../core/crates/layerfs-workspace/src/base/cache.rs): bounded standard +- [`cache.rs`](../../engine/crates/layerfs-workspace/src/base/cache.rs): bounded standard maps store immutable bytes and recency. Large entries can bypass retention. -- [`owner.rs`](../../core/crates/layerfs-daemon/src/overlay/owner.rs) and - [`credits.rs`](../../core/crates/layerfs-daemon/src/overlay/credits.rs): short SQL service +- [`owner.rs`](https://github.com/Ephemeral-AI-Lab/layerfs/blob/c6df039e63187da1f407843540c37477c9e25beb/core/crates/layerfs-daemon/src/owner.rs) and + [`credits.rs`](https://github.com/Ephemeral-AI-Lab/layerfs/blob/c6df039e63187da1f407843540c37477c9e25beb/core/crates/layerfs-daemon/src/credits.rs): short SQL service and aggregate admission credits, including caller-retained result ownership. -- [`db.rs`](../../core/crates/layerfs-overlay/src/database/connection.rs), - [`profile.rs`](../../core/crates/layerfs-overlay/src/database/profile.rs) and - [`schema.sql`](../../core/crates/layerfs-overlay/sql/schema.sql): one initialized +- [`db.rs`](../../engine/crates/layerfs-overlay/src/database/connection.rs), + [`profile.rs`](../../engine/crates/layerfs-overlay/src/database/profile.rs) and + [`schema.sql`](../../engine/crates/layerfs-overlay/sql/schema.sql): one initialized disposable connection, read-back settings and Workspace-prefixed relations. The [base access guide](../../core/docs/architecture/20-workspace-base.md), [daemon owner guide](../../core/docs/architecture/21-daemon-owner.md) and [Store length-fact guide](../../core/docs/architecture/24-file-lengths.md) describe the implemented seams. Source directory presence alone does not establish -an active mounted product; [the core manifest](../../core/Cargo.toml) identifies +an active mounted product; [the core manifest](../../Cargo.toml) identifies active members. ## 3. Different branches safely reuse identical objects diff --git a/docs/general/sdk.md b/docs/general/sdk.md index 6431d7f25..e492beeed 100644 --- a/docs/general/sdk.md +++ b/docs/general/sdk.md @@ -6,7 +6,7 @@ > gate. Owner direction of 2026-10-12 governs the implementation and measurements. > > Relocation 2026-10-15 ([#327](https://github.com/Ephemeral-AI-Lab/layerfs/issues/327)): -> the crate is renamed `layerfs-sdk` -> `layerfs-api` at `core/crates/layerfs-api` +> the crate is renamed `layerfs-sdk` -> `layerfs-api` at `api/layerfs-api` > and regrouped as `project/`, `branch/` and `sandbox/`; links below follow the move. > The layout table stays pinned to `ce4e214d9`. See `core/docs/issues/327/SPEC.md`. > @@ -55,7 +55,7 @@ correlation, retries a failure or silently cleans up an uncertain resource. ## Project -[Init](../../core/crates/layerfs-project/src/store/init.rs) lives in +[Init](../../engine/crates/layerfs-project/src/store/init.rs) lives in `layerfs-project::store`, re-exported by `layerfs-api`. The Node binding calls that same Project implementation directly. Init imports the complete native tree, including Git metadata, ignored files, dependencies, symlinks, caches and @@ -67,12 +67,12 @@ Every permitted new Store explicitly selects Disposable/WAL/synchronous=OFF. Init publishes its original initial Layer and Branch, seals the sole Store, and returns a closed file and the actual original acknowledgements. -[Fork](../../core/crates/layerfs-api/src/branch/fork.rs) preserves the original +[Fork](../../api/layerfs-api/src/branch/fork.rs) preserves the original explicit ForkRequest and its Layer or Commit source. It does not invent a latest head lookup or a hidden refresh. The history trunk is a LayerStack, not a Branch; the first working Branch is named main today. -[Branches](../../core/crates/layerfs-api/src/project/list_branches.rs) reads one page of a +[Branches](../../api/layerfs-api/src/project/list_branches.rs) reads one page of a selected stack in name order, with id, name, base Layer and head Commit. It uses one authorized additive Bridge request (tag 14), one reply (tag 17) and one daemon dispatch arm to the existing HistoryCatalog::branches port. The existing control @@ -80,14 +80,14 @@ window is 32 records. The existing authenticated History cursor covers further pages; the caller advances it explicitly. The SDK checks stack identity, result size, ordered names and continuation shape without a second request. -[Commits](../../core/crates/layerfs-api/src/branch/list_commits.rs) renames the public +[Commits](../../api/layerfs-api/src/branch/list_commits.rs) renames the public history method. It sends the unchanged History request and returns one anchored, bounded ancestry page, newest first. Cursor authentication, captured-head scope, publication semantics and original control bytes are unchanged. ## Sandbox -[Create](../../core/crates/layerfs-api/src/sandbox/create.rs) uses the original +[Create](../../api/layerfs-api/src/sandbox/create.rs) uses the original explicit deployment/image/volume, private configuration, executable, authentication keys and startup wait. For a fresh Store it creates, uploads, starts, authenticates, sends the original initial Hello, installs the sealed Project once, then waits on @@ -98,7 +98,7 @@ startup and sends no second install. Its manifest must match the supplied Projec only the populated daemon SQLite version may differ from the host Init manifest. A mismatched selection fails at Validate before deployment or control effects. -[Close](../../core/crates/layerfs-api/src/sandbox/close.rs) consumes the owner. It +[Close](../../api/layerfs-api/src/sandbox/close.rs) consumes the owner. It attempts the original one-second stop once, then deletes once after acknowledged stop, with force=false and v=false. Stop failure does not attempt delete. Either failure retains exact runtime, control, original inputs, handshake, observation @@ -110,14 +110,14 @@ or command/descriptor drain. The caller explicitly unmounts Workspaces first. ## Workspace -[Mount](../../core/crates/layerfs-api/src/sandbox/mount.rs) takes no Project argument; +[Mount](../../api/layerfs-api/src/sandbox/mount.rs) takes no Project argument; the Sandbox has already selected its Store. It sends the original bind and attach requests once each. The first acknowledgement carries the selected Branch/root; the second carries the mounted directory and native negotiation receipt. A failed attach retains the bound token in MountFailure. No bind, attach, unmount or rollback is guessed from a lost reply or attempted again automatically. -[Exec](../../core/crates/layerfs-api/src/sandbox/exec.rs) delegates ordinary existing +[Exec](../../api/layerfs-api/src/sandbox/exec.rs) delegates ordinary existing Sandbox execution with the mount as working directory and the deployment's admitted identity. It returns the original runtime owner for Start, streams, exit status and explicit cancellation. It sends no daemon control request, registers no filesystem @@ -125,12 +125,12 @@ Exec, applies no ordinary command deadline, and performs no Commit or unmount. Any other permitted process can use the same mount through ordinary filesystem calls; the filesystem daemon supervises no commands. -[Commit](../../core/crates/layerfs-api/src/sandbox/commit.rs) captures the shared +[Commit](../../api/layerfs-api/src/sandbox/commit.rs) captures the shared published frontier and returns Committed or UpToDate. It does not filter mutations -by launch route or command completion. [Status](../../core/crates/layerfs-api/src/sandbox/status.rs) +by launch route or command completion. [Status](../../api/layerfs-api/src/sandbox/status.rs) retains the existing maintained-state scope and never resolves an unknown operation. -[Unmount](../../core/crates/layerfs-api/src/sandbox/unmount.rs) folds normal and +[Unmount](../../api/layerfs-api/src/sandbox/unmount.rs) folds normal and forced terminal operations into `unmount(token, force)`. Normal success returns None; forced success returns Some(ForcedOutcome) with the original dispositions. Normal Busy keeps the mount usable. Public force does not relinquish unknown @@ -195,7 +195,7 @@ src/ [1444] unmount.rs 33 ``` -SDK tests live under core/crates/layerfs-api/tests; affected daemon tests and +SDK tests live under api/layerfs-api/tests; affected daemon tests and benchmark runtime tests remain in their owning external test directories. ## Decisions and deferred work diff --git a/docs/general/workspace-filesystem-view.md b/docs/general/workspace-filesystem-view.md index cfce35ac5..5363e051a 100644 --- a/docs/general/workspace-filesystem-view.md +++ b/docs/general/workspace-filesystem-view.md @@ -155,9 +155,9 @@ before the daemon is contacted. ## 3. Global Store ownership belongs to layerfs-persistence The global Store provider comes from -[`layerfs-persistence`](../../core/crates/layerfs-persistence/src/store/open.rs). +[`layerfs-persistence`](../../engine/crates/layerfs-persistence/src/store/open.rs). The host application selects -[`PersistenceConfig`](../../core/crates/layerfs-persistence/src/store/config.rs) and +[`PersistenceConfig`](../../engine/crates/layerfs-persistence/src/store/config.rs) and creates or opens `Handles`. Those handles supply storage and history providers over one combined host database. diff --git a/engine/AGENTS.md b/engine/AGENTS.md new file mode 100644 index 000000000..8da019f6a --- /dev/null +++ b/engine/AGENTS.md @@ -0,0 +1,585 @@ +# Agent rules for engine + +> **Status:** Current general guide. + +Read [repository instructions](../AGENTS.md) first. This file adds implementation +boundaries for the engine layer under `engine/`; it does not repeat the +product mental model or campaign-specific benchmark procedures. + +## Scope and ownership + +- Engine owns Bridge, daemon, FUSE, Overlay, Persistence, Project, Sandbox, + Store service and Workspace. Core owns content, history, storage and telemetry. + The v0.1.6 reference under + root `crates/` and the archived `core/reference-tests` were retired by R9c + (2026-10-10) and are absent at HEAD; recover them at + local tag `reference-v0.1.6-final` (`d296981ac`, `crates` tree `498dd1917812`). + Neither was a dependency, source include or fallback; do not restore them. +- Active cluster-one members are content, storage, history, persistence, project + Init and telemetry. The initial cluster-two SQLite engine is `layerfs-overlay`; + its active membership does not complete Workspace/FUSE/daemon integration. + [Cargo.toml](../Cargo.toml) is the membership authority. + Workspace now exposes immutable base binding/read, effective source-qualified + lookup/stat/paged name merge, prepared actor install and atomic ordinary + namespace operations, bounded writes/truncate/regrow and composed payload + reads. Independent file/captured/operation custody and bounded live reclamation + are implemented through S6, including indexed automatic reclamation (its + physical reservation and headroom were removed by #321: no space is reserved + ahead of use, and a full device rolls the write back as no space); + native/runtime/integrated exits remain + unfinished. See [S6 audit](../core/docs/issues/307/S6-EXIT-AUDIT.md). Its relocated + predecessor `layerfs-workspace-legacy` was removed by R7-retire. + Since #321 the daemon holds one overlay file and connection per mounted + Workspace, each behind its own lock, with the calling thread running each + short job; the fair SQL owner thread, its queue, credits and shared memory + budget are removed. See the [terminology guide](../core/docs/architecture/64-overlay-terminology.md) + and the [#321 record](../core/docs/issues/321/CHECKLIST.md). + Daemon also exposes a direct global Store adapter with a + mount-time reader per Workspace, exact quarantine and read-only bind snapshots, + one immutable cache shared across Workspaces, bounded root + binding and operation-owned exact failures. Concrete opening stays outside + the provider-independent adapter; see the + [direct Store boundary](../core/docs/architecture/61-direct-store-adapter.md). + The host-mediated SDK/upstream transport is retired; see + [the retirement record](../core/docs/issues/307/PRE-S8-F12-20261007.md). + Workspace calls return typed values directly and count SQL/payload/allocation + work under the same lock. Exact attempted failures retain their cause and + backing; before-effect refusals retain their original input. Overlay/Daemon + also expose bounded indexed operation records in the same database, with guarded atomic changes and automatic last-owner + cleanup. Content now exposes a backed file editor over these records and + Workspace supplies an explicit operation/file adapter with first-original + failure custody. Run-aware localized edits reuse the frozen sparse scanner + and bounded positive immutable zero evidence. Streamed directory inputs share + the canonical filesystem algorithm; backed serial state supplies new-parent + membership, rebuilt roots and initial counts/final row streams. On the backed + route validation classifies in 64-row windows and keeps its topology evidence + in indexed records; resident routes keep their resource-derived limits. + Captured local inode/run points retain exact reader root/floor and bounded + forward metadata progress. Captured regular-file normalization now derives + authenticated base facts, coalesces final changes into indexed records and + consumes them once through the retained FileView/fallible edit source. Backed + reference reduction/release uses fixed rows, sealed membership passes and + guarded FIFO/cursor transitions. Captured namespace normalization is the + `CapturedNamespace` producer + ([captured namespace construction](../core/docs/architecture/78-captured-namespace-construction.md)); + the product Commit constructor calls it + ([product Commit](../core/docs/architecture/79-product-commit.md)). The Store + half of Commit is implemented with exact original failure/unknown custody; + see [Store Commit](../core/docs/architecture/65-store-commit-composition.md). + The external E01 example records original startup work, diagnostics and Stop + without creating a Workspace route. It supplies diagnostic receipt consistency, + not E1/E2 performance admission. Its relocated predecessor was removed by + R7-retire; standalone native executable/Exec integration is unfinished. + Pre-S8 direct-operation accounting now has actual registered macOS/Linux engine + and Store-half Commit runs, independent family/count validation, and supported + phase observations. Numerical latency/residency and exact continuous peaks + remain unqualified; see the [accounting scope](../core/docs/issues/307/PRE-S8-F14-20261007.md). + SDK creates/imports the initial Store, publishes the first Branch and consumes + seal, returning a closed file plus explicit provider/locator/profile metadata. + It retains no Store handle or data service. Native install now streams the + sealed file once, opens it in the daemon and returns both actual SQLite versions; + see [F5 handoff](../core/docs/issues/307/PRE-S8-F5-20261007.md). Authenticated mount + binding, Store-half Commit, status, terminal close, fork and history now compose + the direct ports; see [native control](../core/docs/architecture/68-native-workspace-control.md). + The prior client/runtime, daemon upstream, Bridge logical data framing and + excluded API-core are retired. Historical receipts keep their original topology + and verdicts. R7-retire (2026-10-10) + removed all seven excluded directories as retirement: `layerfs-server`, + `layerfs-fuse-legacy`, `layerfs-sandbox-legacy`, `layerfs-sdk-legacy`, + `layerfs-daemon-legacy`, `layerfs-bridge-legacy` and + `layerfs-workspace-legacy`. The root workspace lists the active + members across core, engine and api; the boundary guard refuses the return of a removed directory or + package name, and each source is recoverable from the commit named in the + [R7-retire record](../core/docs/issues/307/R7-RETIRE-COMPLETION-20261010.md). + Pinned read-only SDK views (303/08 O-10) are deferred, not dropped: no + implementation is in the tree, and a kept feature needs a new design on the + SQLite overlay. Do not restore the predecessor code to supply them. + Project native import preserves opaque symlinks, complete membership and hard + links, with indexed acquisition state. The accepted host WAL baseline retains + its recorded speed FAIL; no new timing is implied by SDK composition. + Bridge retains pinned authenticated KK channels, bounded native records and + independent fences and bounded native install/control. FUSE/Exec qualification + and complete kernel mount readiness remain S8. + The replacement Sandbox is an active member with ordinary Engine execution, + owned lifecycle and authenticated SDK/daemon startup. Optional privileged + command cancellation/client provenance is outside the current owner scope. + The replacement Fuse is now active with a fixed shared dispatcher, actual + deferred Owner/Store ports, a read-path callback adapter with complete opcode + accounting, direct mount/session ownership and connection drain. + Its predecessor `layerfs-fuse-legacy` was removed by R7-retire; the last + commit holding that source is `15e33e22c`. The daemon + composes Attach/Locate/Ready and reversible normal unmount; see + [native request service](../core/docs/architecture/75-native-request-service.md) and + [native mount session](../core/docs/architecture/76-native-mount-session.md). + Ordinary native mutation is served through the existing Workspace plan and + one publishing Overlay job, with no notification and no writeback cache; see + [native mutation and kernel coherence](../core/docs/architecture/77-native-mutation-coherence.md). + A control Commit runs the captured namespace producer through the unchanged + driver, and takes the Workspace's overlay lock for each of its jobs; the mounted + proofs and their limits are in the + [R5 record](../core/docs/issues/307/R5-COMPLETION-20261009.md). Forced unmount of one + Workspace is implemented as `ForceUnmount`: a before-effect guard, one abort + write on the connection's own control, the terminal fence, the local drain, + one plain detach, then Revoke and Close; see + [forced teardown](../core/docs/architecture/80-forced-teardown.md). It is refused where + no abort control is bound, which includes the current Sandbox topology, and a + stop after an effect is `Retained` with no way back. No daemon-wide graceful + drain exists and none is planned. Source acquisitions have their own owner + slots, and a failed cold read ends its own request with `EIO` while the + mount keeps serving; the concurrency, teardown and failure-scope proofs and + their limits are in the [R6 record](../core/docs/issues/307/R6-COMPLETION-20261009.md). + A create that leaves fewer unconsumed inode serials than the daemon's + configured low-water makes one early reservation; every deployment and + harness sets 0 today, which makes none. A new Mount is refused `Capacity` at + `mount:debt` while maintenance is stopped. Both, the proofs added around + them and the rows still open are in the + [R8b record](../core/docs/issues/307/R8B-COMPLETION-20261010.md). R8b closed not + qualified and R9b without removal. R8c then closed qualified on function, + counts and resources at the owner-rescoped scope, with the deployed + low-water at 256 ([R8c record](../core/docs/issues/307/R8C-COMPLETION-20261010.md)), + and R9c retired the root reference + ([R9c record](../core/docs/issues/307/R9C-COMPLETION-20261010.md)). + Add members only with real product boundaries and implementation. +- Cluster-one work starts with the [handbook](../docs/general/cluster_one_handbook.md) and + [CAS/CDC/delta guide](../docs/general/cas_cdc_deltaencoding_handbook.md). Use public contracts, + source pins and limitations; preserve canonical compatibility. +- Cluster-two work starts with the [current design index](../core/docs/issues/303/README.md) + and relevant primary operation/engine/FUSE contracts plus + [runtime integration](../core/docs/issues/303/06-cluster-one-integration.md). + Required corrections are real engineering scope; research candidates are not + implemented features or excuses for accumulated workload caps. +- Closed Stage 0–6 handoffs and prior server/backend plans are historical. + Consult them for a selected compatibility/reference question; do not restart + their loops or inherit their retired topology. Do not revive `layerfs-server`. +- Keep unrelated work intact. Migration, source moves and retirement are explicit + changes, not side effects of implementing a component. + +## Architecture and public contracts + +Overlay schema19 uses `directory_entry` and `operation_record` terminology, +including owned/indexed variants, throughout SQL and the active public ports. +Through schema 33 Workspaces shared physical tables partitioned by namespace; +since #321 (schema 34) every mounted Workspace has its own file with the same +tables, copied from a closed empty template at mount and deleted at terminal +unmount. The naming +change authorizes no physical table redesign; generic temporary buffers and +historical receipts retain their distinct terms. See the +[terminology guide](../core/docs/architecture/64-overlay-terminology.md). +The #320 product sweep (2026-10-14, schema 37) removes accounting triggers, +Workspace/allocator SQL rows and generic caller-minted leases. Workspace +lifecycle/frontier/dirty/base-reader counters are one journaled runtime value, +restored only after known whole-job rollback; unknown outcomes retain custody. +Commit runs/readers/base pins are journaled owner maps; captured generation +holds use a count index. Daemon-bound routing is checked once per call; Overlay +accepts no Route and stores no namespace. Cleanup debt remains SQL-backed after +the [memory-placement review](../core/docs/issues/320/CLEANUP-MEMORY-DESIGN-20261014.md). +Resources computes row/length totals on demand and +retains exact owner counts from memory. See the current +[runtime state](../core/docs/architecture/64-overlay-terminology.md#runtime-workspace-state-and-remembered-sql-custody). + +Schema17 adds native mount/source/lookup/read associations, atomic Workspace +read observations and bounded revoked-lookup retirement. Schema18 adds native +file associations over the existing OpenFile owner and atomic open decisions; see +[native read custody](../core/docs/architecture/73-native-read-custody.md). This component +does not establish Ready, kernel service or full drain. Schema19 adds native +directory ownership, exact name-boundary cookies, retained parent updates and +bounded live cleanup; see [directory custody](../core/docs/architecture/74-native-directory-custody.md). + +`docs/architecture/` describes product source, not release qualification. +A source change to boundaries, canonical/physical format, algorithm or named +bound updates the affected architecture/API document in the same change. +Record source pins and advance them explicitly; never silently re-date evidence. +Keep implementation description separate from target proposal and research. + +Public content/storage/history/persistence contracts govern integrated callers. +Stable capture/input, Store-derived policy, backpressure, Save completion and +atomic history publication are separate obligations. Branch Commit overwrites the +head and keeps its captured parent; see the [owner supersession](../core/docs/issues/307/BRANCH-OVERWRITE-DECISION-20261007.md). Immutable objects do +not replace authority, reference closure, mutable history or safe GC. + +Project's native import consumes SQLite-backed acquisition through its +backend-neutral port. Its Store composition lives in `layerfs-project::store`: +Init creates and seals the Store, and install streams the sealed file. The +owner-approved first-party edges include Bridge provisioning types and +Persistence; the exact allowlist still bounds those edges, and Project still +cannot use a third-party database driver directly. Canonical construction stays +in Content, encoding/packing in Storage and database writes in Persistence. +The port and its provider remain the existing indexed acquisition algorithm. +See the [S7/S9 remaining plan](../core/docs/issues/307/IMPLEMENTATION-PLAN-S7-S9-20261006.md). + +### Filesystem access and execution ownership + +Owner clarification 2026-10-08: these are implementation and proof requirements, +not a claim that S8 or S10 is qualified. FUSE serves any permitted process that +can see the mount. Request admission and Workspace mutation/capture must not +require an Exec identity, registered command or LayerFS-launched parent. +Apply the same permissions, filesystem semantics and ownership to external +executors, interactive shells and ordinary Sandbox execution. + +Sandbox setup or the external executor establishes command identity, mount +visibility and protection of Store, Overlay and daemon credentials. Ordinary +runtime execution owns standard I/O, exit status and caller-requested cancellation. +SDK public organization is the eleven operations documented in +[the implemented SDK surface](../docs/general/sdk.md), with operation files under +[layerfs-api/src](../api/layerfs-api/src). Project offers init/fork/ +branches/commits; Sandbox offers create/close; Workspace offers mount/exec/ +commit/status/unmount. Shared control/recovery/diagnostic plumbing lives in +base/ and the hidden internal module. Optional WorkspaceApi.exec selects the +mounted directory and delegates the existing Sandbox launcher; +the daemon has no exec/supervisor, launcher mode, per-Exec cgroups, command +registration or custom Exec stream/status/cancellation protocol. + +FUSE owns exact request/open/lookup/capture/Commit lifetimes and complete +filesystem/daemon-work drain. Zero registered commands or shell exit is never +evidence of released descriptors, mappings, kernel references or daemon jobs. +Forced filesystem teardown does not implicitly kill caller-owned processes. +Normal unmount uses a reversible kernel busy probe while ordinary service stays +usable. Force refuses active namespace control producers before any effect. + +Commit consumes the Workspace's published frontier through the shared Content, +Storage and Persistence pipeline regardless of launch route. stdout/stderr are +not filesystem state unless the command writes them to a file in the Workspace. +The old proposed managed-daemon Exec selections are withdrawn prospectively; +retain their original IDs, source pins, receipts and verdicts. Ordinary runtime +stream/result correctness and filesystem-lifetime proofs keep their real owners. + +S8 verification must include a process launched outside the Exec API, with no +Exec registration, reading and mutating the mount and retaining a filesystem +reference during an unmount attempt. S10 must prove that such changes survive +Commit and a fresh mount. Use ordinary public filesystem access in these proofs. + +Reviewed target source ownership2026-10-08: the replacement `layerfs-fuse` owns +its complete native connection/request service, including bounded dispatch, +parking/resumption, kernel handlers/replies and coherence. Daemon assembles one +shared Fuse service with its existing SQL/Store services, retaining registry, +overall Ready/unmount and Commit composition. Dependency is daemon -> fuse -> +workspace, never Fuse -> daemon. Request dispatch/read ports, mount/Ready and +per-Workspace normal drain are implemented ([R2 record](../core/docs/issues/307/R2-COMPLETION-20261008.md)), +as is ordinary native mutation ([R3 record](../core/docs/issues/307/R3-COMPLETION-20261008.md)); +as is the captured namespace producer with its bounded validation +([R4 record](../core/docs/issues/307/R4-COMPLETION-20261008.md)), which the Commit +driver reaches through the product constructor +([product Commit](../core/docs/architecture/79-product-commit.md)). See the +[reviewed ownership](../core/docs/issues/307/R2-R5-SOURCE-OWNERSHIP-REVIEW-20261008.md). +Moving blocking OwnerClient calls behind a port does not establish deferred service. + +### Shared construction and completion boundaries + +Source checked at `5747f0119`, guidance updated 2026-10-08. Namespace Init and +daemon construction share Content, Storage and Persistence through their public +ports. Their input adapters and publication lifecycles have distinct owners: + +| Input/operation | Existing route | +| --- | --- | +| Native Init file | Project import calls Content `construct_stream`; bounded output batches feed `Save::accept` | +| New captured file | Workspace `CapturedFileEdits` calls Content `construct_runs` over data/zero windows | +| Existing captured file | The same adapter calls `apply_indexed_edits_view_backed` over an authenticated retained `FileView` and normalized final edits | +| Initial namespace | Project streams acquired bindings/inodes through Content directory/table builders | +| Captured namespace | Workspace `CapturedNamespace` seals headers, typed values and fresh ranks into indexed records and calls Content `update_filesystem_streamed_backed`; names come from the retained captured reader | +| Captured symlink and metadata | The same producer calls Content `emit_symlink` for a fresh target and patches or builds the portable attribute tree; a stored symlink keeps its base content root | +| Object output | Content emits `FinalizedObject`; Storage `SaveSink` implements `FinalizedConsumer` by forwarding to `Save::accept` | + +Use the actual Store-derived construction policy and bounded capacities on +both routes. Fresh construction and incremental edits use appropriate public +entrypoints and common canonical formats; do not assume an incremental file root +must equal a fresh full reconstruction, since retained chunk boundaries can differ. +Overlay owns mutable payload, metadata, operation records and construction scratch +under Workspace prefixes. Content owns canonical algorithms; Storage owns +deduplication, encoding and packs; Persistence owns global Store writes. Keep +SQLite types and paths out of Content and the daemon's provider-independent +`store/` adapter. Do not materialize a native tree or invoke Project Init to +implement a Workspace Commit. Native Init acquisition backing remains a separate +host provisioning facility. + +Current source has captured-file normalization and the Store half of Commit. +`BoundWorkspace::commit` captures once, begins a Save, invokes a caller-supplied +Content constructor, finishes the Save, publishes through History and installs +the known root locally. Full captured namespace assembly, including names, +links, metadata and changed file roots, is +[`CapturedNamespace`](crates/layerfs-workspace/src/construction/driver.rs). +The product constructor `BoundWorkspace::commit_captured` runs it inside that +driver: it acquires the captured reader and one operation owner, hands the +driver the original cause on failure, and releases both owners only after the +driver's outcome is known, keeping them with the failure when it is not +([product Commit](../core/docs/architecture/79-product-commit.md)). A control Commit +uses it; `Service::execute` still takes a caller's constructor for driver tests. +See [captured-file construction](crates/layerfs-workspace/src/construction/captured/owner.rs), +[the shared Save sink](../core/crates/layerfs-storage/src/save/operation.rs) and +[Store Commit composition](../core/docs/architecture/65-store-commit-composition.md). + +Keep completion boundaries explicit: `Save::finish()` completes object storage; +Init then initializes history, while Commit calls `commit_branch` against its +expected head before local base installation. SDK Init subsequently calls `Handles::seal()` to +checkpoint, close and hand off one Store file. The macOS allocation correction +runs only at this sole-owner Store seal; it is not a Content/pack format change +or live-daemon maintenance. Linux daemons keep their shared Store open. The +[seal proof](../core/docs/issues/307/SEAL-ALLOCATION-STRIDE1-20261007.md) retains its exact +platform and benchmark scope; it does not qualify daemon allocation or S10. + +## Optimization and performance debugging + +Before changing a performance-sensitive path or diagnosing a performance finding, +read the [optimization guide](../docs/general/optimization-guide.md). Its FUSE, +SQLite and complexity rules are mandatory: reject quadratic or worse scaling, +use SQLite-backed mutable indexes/state rather than custom duplicate trees/graphs, +and account for request/SQL/IO/copy/residency/cleanup work. Preserve cluster one's +canonical formats and public APIs; use count-driven evidence and the existing +measurement policy. SQLite debugging/optimization claims require both database +EXPLAIN and correlated runtime database profiling; overall wall time or a plan +alone is insufficient. An unrelated/docs-only change does not require a campaign. +The [optimization handbook](../docs/general/optimization-handbook.md) is the +working procedure on top of those rules: the counters that already exist, the +diagnostic groups, the scaling checks and the current candidate list. + +## Product source and external verification + +The Rust `src/` directories in core, engine and api contain production code +exclusively, including +included/generated implementation. Runtime SQL and other shipped implementation +have the same ownership rules. + +Forbidden in product source: inline tests/benches, test-only cfg/features, +fixtures, mocks, fake clocks, fault injection, test/benchmark drivers, test-only +public APIs, benchmark-selected algorithms and executable rustdoc test blocks. +Platform cfgs, real features, production validation/invariants and actual telemetry +remain legitimate. Put API documentation with the API; examples outside src. + +| Content | Location | +| --- | --- | +| Product implementation | Core/engine crate `src/`, API Rust/JavaScript `src/` and required runtime source | +| Public-API tests and their helpers/fixtures | Package `tests/` | +| Runnable examples | Package `examples/` | +| Package benchmarks | Package `benches/` | +| Product-wide harness/diagnostics | the [layerfs-benchmark](https://github.com/Ephemeral-AI-Lab/layerfs-benchmark) repository; inspect the actual harness manifest/entrypoint | +| Development checks | `tools/` | + +Tests exercise the production library that normal consumers use. Do not +include/recompile private source, redirect target paths into test directories, +import helpers into production or expose an API only to enable a test. +Test-only dependencies belong in dev-dependencies; retain component-specific +restrictions, including std-only telemetry. + +Prefer deterministic public behavior and external observations. Telemetry tests +can use completed reports and structural ordering; do not add a product fake-clock +interface or narrow sleep-based wall thresholds. Verify disabled behavior through +its actual allocation/clock path. Scaffold no empty placeholder directories. + +## Production file size and responsibility + +All new replacement/application-adapter production files have at most **999 +physical lines**, including comments/blanks. This includes required runtime SQL +or other shipped formats outside Rust src. Extend guard coverage for new formats; +moving implementation does not evade the rule. The legacy root source is +retired; do not recreate a root `crates/` for product work. + +Every product `lib.rs`/`mod.rs` has at most **200 physical lines**. These files +contain attributes, declarations, imports/reexports, API docs and thin forwarding. +Definitions, impls, state/constants encoding behavior, branching, loops, conversions, +validation, formatting and I/O belong in focused named implementation files. + +Split by responsibility before the ceiling: lookup, transactions, reconstruction, +placement and ownership, not numbered files or a renamed god module. Use ordinary +functions/concrete types; do not add a factory/interface per algorithm or a +service locator. Keep actual process/provider boundaries independently usable. +Do not minify, expand macros or add includes to evade size/ownership rules. + +Physical line ceilings differ from production LOC. Follow the root +[per-commit LOC policy](../AGENTS.md#production-loc-comparison-for-every-commit) +using exact parent/staged/committed trees and migration subtotals. Docs, tests, +fixtures, examples and tools do not contribute to production LOC. + +## Failure, persistence and dependencies + +- One attempted operation; no automatic retry, busy handler, refresh/reprepare, + error-driven algorithm/backend/reference substitution or guessed recovery. + Readiness waits and explicit cancellation have their own state before an + attempt; they do not permit replay after failed/unknown publication. +- Preserve definite-failure atomicity, original errors and exact uncertain + custody. No resend, rollback/delete or success claim based on an unfenced read. +- Global Persistence uses **Disposable/WAL/OFF only**, on macOS and Linux, + under the [owner's active-profile rule](../AGENTS.md#active-persistence-profile--owner-direction-2026-10-07). + Durable execution is disabled indefinitely until explicit owner reauthorization; + retained Durable source may compile but no test, diagnostic, measurement or + application invocation may execute it. Select Disposable explicitly rather than + relying on a default argument. Disposable claims process-crash survival only. + Open verifies WAL and never converts an + existing Store. Select profile/layout before open; Postgres stays unavailable. + Owner supersession2026-10-07 keeps WAL throughout Init and Commit; no private + MEMORY import or journal promotion remains. The measured host Init regression + is retained as FAIL and accepted as the new baseline for that exact scope. + Host seal consumes sole ownership, checkpoints, closes and verifies one file. + Its macOS completion releases unused extents beyond logical EOF through the + existing safe nix API, preserving the original file's bytes and identity. + This narrow seal-only correction does not restore per-pack preallocation or + the allocation owner, and is never invoked on a live shared daemon Store; see + the [seal boundary](../core/docs/architecture/60-shared-store-foundation.md). + See the [foundation checkpoint](../core/docs/issues/307/PRE-S8-F1-F4-20261007.md). +- Target (owner direction 2026-10-07): the same Store opened directly by every + Linux daemon from a shared volume, several writer processes, no host in the + data path, using only Disposable/WAL/OFF. A contended + write still has one SQL attempt and exact failure/unknown custody. Owner + clarification2026-10-12 requires one ongoing Commit per Workspace and allows + concurrent Commits on different Workspaces. Bounded before-effect admission + now queues SQL work within a Session and coordinates short Linux writer jobs + on the existing local Store parent-directory inode; multiple Store files in + one directory share this coarse short-transaction lane. Do not open/close a + separate main/WAL/SHM descriptor for advisory ownership: closing a main-file + descriptor can cancel SQLite's own process POSIX locks. This admission does + not gate whole Saves or Commits or replay + a failed SQL attempt. macOS has Session admission only; separate macOS writers + and uncoordinated raw SQLite writers retain exact Busy refusal. Follow the + [integration contract](../core/docs/issues/303/06-cluster-one-integration.md) and its + [deepest-file plan](../core/docs/issues/307/SERVERLESS-STORE-PLAN-20261007.md); do not + extend the host-mediated SDK runtime, Bridge data codec or daemon upstream. +- Store concurrency (owner decision 2026-10-18): one global database and one + writer at a time are the design, not a limitation to engineer around. Keep + the existing admission, directory lock and publication lane; shorten what + runs inside the lane (only head check, merge and publish) instead of adding + writers or databases. Judge speed on uncontended calls; contention must stay + correct, bounded and exact. See the + [Store concurrency model](../core/docs/architecture/83-store-concurrency-model.md). +- The daemon overlay is a separate owner/profile from global persistence: + one local database file per mounted Workspace, opened MEMORY/OFF/EXCLUSIVE by + one connection behind that Workspace's lock. Workspaces share no overlay + connection, page cache or memory budget. It is not an implemented distributed Store or a universal + global-Store rule; reader-pool alternatives need their own proofs. +- WAL/sync are permitted for a declared global Store profile. Do not add + fsync/fdatasync/sync_data/sync_all on disposable Workspace backing. Memory + hints do not prove bounds. Claim only actual completion/durability contracts. +- No third-party patch, fork, vendor, registry edit or replacement dependency, + except the owner's fuser 0.18.0 signed-timestamp correction below. + Use existing capabilities and locked builds; report an incompatible required + dependency with source evidence. Unsupported required platforms/capabilities + fail explicitly, not via a silent no-op or fallback. + +## Checks and completion + +Run commands from the repository root with the root workspace manifest. For product, +API, manifest or runtime-source changes, cover tests/examples, warning-denying +Clippy and formatting, plus the boundary guard and its self-tests: + +```sh +cargo +1.85.1 test --locked --all-targets --no-run +# Execute the compiled tests per package under an explicit timeout <=120 s. +cargo +1.85.1 clippy --locked --all-targets -- -D warnings +cargo +1.85.1 fmt --all -- --check +python3 -B tools/check_product_boundary.py +python3 -B -m unittest discover -s tools -p 'test_*.py' +``` + +Every test invocation obeys the repository's +[2-minute test ceiling](../AGENTS.md#4-code-build-and-docs): run it under an +explicit timeout of at most 120 s, per package when the whole suite cannot fit, +and treat reaching the ceiling as a hang to diagnose, not a run to wait for. + +Migrations and refactors follow the root +[delete-rather-than-nurse rule](../AGENTS.md#4-code-build-and-docs): delete a +test that is tricky to adapt, keep or move only cheap tests of surviving +behaviour, and re-cover any still-valid fix or contract on the new code. +fs-bench-pro (in layerfs-benchmark) is frozen and left broken (owner, 2026-10-18): +do not build, run, check or repair it. + +For docs-only changes, check links/anchors, status/claim accuracy and whitespace; +report why Rust/runtime checks are inapplicable. For tooling/harness changes run +the owning scoped tests. At final implementation identity run required covering +checks once; diagnose a failure from its output/source before a justified repair +and rerun. Do not repeat unchanged passing checks or run an unrelated legacy sweep. + +The guard checks source text, line caps and common prohibited constructs, +including markers embedded in source comments/strings. It is not a Rust semantic +or runtime proof. Review ordinary macros, helpers, dependency/target declarations +and generated inputs; extend scanners for new shipped formats. An excluded +FUSE/daemon package is not exercised by passing active-workspace tests. + +CI reports after a push and never gates it (see the +[root rule](../AGENTS.md#4-code-build-and-docs)); test lane selection is +[tools/ci_tests.py](../tools/ci_tests.py). When a test target is renamed, moved or +measured at 5 s or more, update its `SLOW` list; Linux-only daemon targets and the named API mount targets go to +the nightly mount lane. There is no pre-push gate; +`tools/preflight.sh` is retired. Do not disable discovery or recreate an +equivalent wrapper. Report exact checks, failures and gaps. A scan or proposal +alone does not establish implementation. + +### Build flags are part of the check + +aarch64 binaries retain the repository ARMv8 AEAD build inputs: +`--cfg aes_armv8 --cfg polyval_armv8 --cfg chacha20_force_neon +-C target-feature=+aes,+sha2`. +The [root Cargo config](../.cargo/config.toml) is discovered from the working +directory, independently of the selected manifest. Builds outside the repository or +with explicit RUSTFLAGS must repeat that profile. Record flags/config in build +identities; preserve the transport's required-profile refusal when integrating +it. Documentation builds do not prove the binary profile. + +Measurement work additionally follows the +[agent measurement workflow](../docs/general/agent-measurement-policy.md) and +[owning core harness guide](https://github.com/Ephemeral-AI-Lab/layerfs-benchmark/blob/main/fs-bench-pro/AGENTS.md). Frozen identities, +cache states and budgets are evidence contracts, not product runtime limits. + +### Fuser provenance and authorized-patch checks + +Additional owner authorization 2026-10-14: "you are allowed to modify fuser with +patch". The [receive-buffer decision](../core/docs/issues/321/FUSER-RECEIVE-BUFFER-DECISION-20261014.md) +records the scope. Receive loops read into the `max_write + 4096` bytes +negotiated at INIT instead of fuser's 16 MiB + 4 KiB maximum. The delta is in +`read_buf.rs`, `session.rs` and `session/lifecycle.rs`, applied after the +lifecycle patch. `receive-buffer.patch` and `receive-buffer-provenance.json` +pin it, and the focused check verifies it. The earlier records stay unchanged. + +Additional owner authorization2026-10-08: the [scoped receive-loop lifecycle +extension](../core/docs/issues/307/FUSER-LIFECYCLE-DECISION-20261008.md) may extend the +pinned fuser0.18.0 package beyond time.rs to establish loop entry/exit, retained +startup/join ownership and the proposed explicit lifecycle API. This narrowly +supersedes the timestamp-only file restriction below. Preserve the original +timestamp provenance unchanged; record and verify the lifecycle delta separately. +No other dependency change or general unsafe exception is authorized. Permission +does not establish implementation or native Ready/drain qualification. + +Latest owner direction2026-10-06: "use fuser 0.18.0 from crates io and apply patch". +This supersedes the earlier registry-only/no-patch ruling for this one correction. +Keep the dependency version exactly0.18.0; use the checked-in copy of its official +crates.io archive with only `src/time.rs` changed by the recorded upstream timestamp +fix and regression tests. Both owning workspace roots use the exact path/version +`[patch.crates-io]` entry. Do not edit shared Cargo registry packages, adopt a Git +dependency, or extend this exception to unrelated source/dependency changes. + +The original archive checksum, all85 published file hashes, exact diff and patched +time.rs hash are pinned in `patches/fuser-0.18.0/provenance.json` and checked by the +focused guard. A patched Cargo.lock entry has no registry checksum; the explicit +provenance record authenticates its modified bytes. See +[the authorized patch record](../core/docs/issues/307/FUSER-REGISTRY-PATCH-20261006.md). +Native qualification and the complete S8 contract remain separate requirements. + +Subsequent owner direction2026-10-06: "docker verification is enough". Existing +native Docker proofs are accepted for verifying this fuser correction. Retain +Linux's fractional signed-minimum endpoint outcome as a platform limitation; +do not require QEMU or a custom-kernel campaign to verify the dependency fix. +This acceptance does not complete S8's product implementation or turn that +individual native FAIL into PASS. Continue the remaining S7–S9 work using Docker. + +Before a native fuser build, run the focused provenance check: + +```sh +python3 -B tools/check_fuser_integrity.py +``` + +For an installed registry source, also supply its archive, package directory and +checksum taken from its original registry lock or the pinned base-archive record +with `--archive`, `--package-directory` and `--locked-checksum`. This reads and +verifies package files without modifying +them. Run scoped self-tests when changing the check. It is not an aggregate +pre-push/CI wrapper or a timestamp-capability proof. Current evidence and the +historically rejected unmodified Git candidate are in +[the fuser verification record](../core/docs/issues/307/FUSER-OFFICIAL-CANDIDATE-20261006.md). + +### Authorized Persistence seal file control + +Owner authorization 2026-10-07: "Approve the narrowly audited seal wrapper". +The system macOS SQLite enables persistent WAL and otherwise leaves empty +sidecars after checked close. Persistence uses `deny(unsafe_code)` with one +allowed module, `src/backend/sqlite/file_control.rs`, compiled on macOS only. +It sets and reads back `SQLITE_FCNTL_PERSIST_WAL` under sole seal ownership. +No other Persistence module may contain unsafe Rust; the guard and its tests +enforce the exact path. This does not authorize third-party patches, dependency +changes, manual sidecar deletion or other FFI. See the +[decision and diagnostic](../core/docs/issues/307/SEAL-PERSIST-WAL-DECISION-20261007.md). diff --git a/engine/crates/layerfs-persistence/README.md b/engine/crates/layerfs-persistence/README.md index 6233b3173..47480eeba 100644 --- a/engine/crates/layerfs-persistence/README.md +++ b/engine/crates/layerfs-persistence/README.md @@ -51,7 +51,7 @@ boundary. Namespace entry-count collections are measured but are not yet a whole-importer memory-bound proof. The current plan and evidence live in -[issue 302](../../docs/issues/302/SQLITE-DESIGN-AND-PLAN.md). Performance qualification +[issue 302](../../../core/docs/issues/302/SQLITE-DESIGN-AND-PLAN.md). Performance qualification requires all seven revised Step 10 selections and the prospectively frozen 10% time margin; unit tests and compilation alone do not complete it. diff --git a/engine/patches/fuser-0.18.0/README.md b/engine/patches/fuser-0.18.0/README.md index 1e10a1ef4..b10c1b4b8 100644 --- a/engine/patches/fuser-0.18.0/README.md +++ b/engine/patches/fuser-0.18.0/README.md @@ -5,7 +5,7 @@ The owner explicitly requested: "use fuser 0.18.0 from crates io and apply patch". This supersedes the earlier no-patch/registry-only ruling for this correction. -`core/vendor/fuser-0.18.0` is a complete copy of the official crates.io archive +`engine/vendor/fuser-0.18.0` is a complete copy of the official crates.io archive originally qualified with only `src/time.rs` changed. Its correction and regression tests are copied from upstream commit [e48279fab0ddbe4a6e22aefad3cbfdf796d0b0b7](https://github.com/cberner/fuser/commit/e48279fab0ddbe4a6e22aefad3cbfdf796d0b0b7). @@ -18,20 +18,19 @@ The input archive is SHA-256 `b82b6597d216503555ead6b358f341ef748869bf5c6fbae6a0cb9dd231baecfd`. [provenance.json](provenance.json) pins all85 original files, the exact [diff](signed-timestamps.patch) and the resulting time.rs. The focused -[integrity check](../../tools/check_fuser_integrity.py) verifies these pins and -both owning `[patch.crates-io]` declarations. Use it before native builds: +[integrity check](../../../tools/check_fuser_integrity.py) verifies these pins and +the root workspace `[patch.crates-io]` declaration. Use it before native builds: ```sh -python3 -B core/tools/check_fuser_integrity.py +python3 -B tools/check_fuser_integrity.py ``` -Cargo applies patches from the workspace root. The core workspace and independent -Linux prerequisite harness each select this exact path with `version = "=0.18.0"`. -The active core graph does not yet contain the replacement FUSE package; its patch -is recorded as unused. The prerequisite harness actually builds the patched crate. -The root reference workspace keeps its existing dependencies. A patched lock entry -has no registry source/checksum: the original archive checksum authenticates the -input, while the diff/file identities authenticate the changed dependency. +Cargo applies this patch from the root workspace, whose active FUSE member +builds the authorized package at `engine/vendor/fuser-0.18.0`. The original +prerequisite harness and its receipts retain their historical source identities. +A patched lock entry has no registry source/checksum: the original archive +checksum authenticates the input, while the diff/file identities authenticate +the changed dependency. This checked-in copy and its patch survive fresh Cargo caches and clean checkouts. Reconstruction is extraction of the pinned archive followed by one application of @@ -41,10 +40,10 @@ verify the result before using it. Builds do not mutate shared registry packages or apply an unrecorded patch. No other dependency receives an exception. Third-party source, including the corrected time.rs, is excluded from first-party -production LOC by the unchanged repository counter. It remains visible as a +production LOC by the repository counter. It remains visible as a dependency correction; it is not a first-party source-size reduction. -The [qualification record](../../docs/issues/307/FUSER-REGISTRY-PATCH-20261006.md) +The [qualification record](../../../core/docs/issues/307/FUSER-REGISTRY-PATCH-20261006.md) separates parser/reply correctness, actual mounted behavior, Linux timestamp boundary canonicalization and the still-incomplete S8 product milestone. Retire this patch only after an explicitly selected corrected release passes the owning @@ -52,7 +51,7 @@ qualification; do not silently switch sources or weaken the timestamp contract. ## Receive-loop lifecycle extension, 2026-10-08 -The owner [authorized this narrow extension](../../docs/issues/307/FUSER-LIFECYCLE-DECISION-20261008.md) +The owner [authorized this narrow extension](../../../core/docs/issues/307/FUSER-LIFECYCLE-DECISION-20261008.md) after inspection showed that the original public API could not report all-loop startup or preserve all joins through its early error paths. The additive `Session::into_runner()` API provides a `SessionRunner`, a `SessionMonitor` and @@ -74,13 +73,13 @@ four exact changed/added files: session.rs, lib.rs, the new session/lifecycle.rs and the local changelog note. There are86 resulting package files. The focused guard requires both exact provenance records and patches and rejects any other changed, missing, redirected or added file. Its original timestamp constants -are unchanged. The [dependency proof receipts](../../docs/issues/307/checks/r2-fuser-lifecycle-20261008/18-proof-summary.json) +are unchanged. The [dependency proof receipts](https://github.com/Ephemeral-AI-Lab/layerfs/blob/55da108f895f425eee254d26f69bc5686ca03861/core/docs/issues/307/checks/r2-fuser-lifecycle-20261008/18-proof-summary.json) include public parser/loop fixtures, real resource-driven partial spawn failure and one native mount/Ready/detach/join. Full LayerFS R2–R5 remains unfinished. ## Receive buffer sized by the negotiated max_write, 2026-10-14 -The owner [authorized this delta](../../docs/issues/321/FUSER-RECEIVE-BUFFER-DECISION-20261014.md) +The owner [authorized this delta](../../../core/docs/issues/321/FUSER-RECEIVE-BUFFER-DECISION-20261014.md) after the dense-rewrite peak investigation. Each receive loop allocated fuser's 16 MiB + 4 KiB maximum although LayerFS negotiates a 128 KiB `max_write`. glibc made those buffers resident from the second mount on: about 32 MiB per diff --git a/tools/substitution-proof/README.md b/tools/substitution-proof/README.md index d3d04cb7c..d23a0e2e0 100644 --- a/tools/substitution-proof/README.md +++ b/tools/substitution-proof/README.md @@ -17,7 +17,7 @@ Four arms, one frozen consumer, four dependency selections: | `combined` | candidate | candidate | ```sh -python3 core/tools/substitution-proof/run.py --baseline 66bce8378 --candidate HEAD +python3 tools/substitution-proof/run.py --baseline 66bce8378 --candidate HEAD ``` The run materializes one revision tree per arm under `--root` (default `/tmp/subst`), From ff7ccee2f6b8fc41c2a3a4c6d58e56cb6af80e4e Mon Sep 17 00:00:00 2001 From: YifanXu1999 Date: Tue, 27 Oct 2026 03:30:11 +0800 Subject: [PATCH 08/10] test(daemon): stage FP-21 provider reads after reader cache warming The caller preparation warms mounted-reader caches even when the shared canonical cache is disabled. Both OPEN and READDIR could finish without reaching the provider gate, so the fixture failed before any unmount attempt. Displace prepared pooled inode values through the same Workspace's public Store ports using 73 valid leaves with 7,300 distinct inline metadata values. The count derives from the existing cache bound. Keep the default policy, all product code, timeouts and original teardown assertions unchanged. Report request, provider and caller state when staging fails. Checks: diagnostic reproduces both original staging failures (10.13 s); final Linux focused proof 2/2 (0.25 s, 90 s command ceiling); separate no-run build; focused Clippy -D warnings; fmt; boundary guard (954 inputs), its 34 self-tests; fuser provenance; record links and whitespace. Original migration failure evidence is retained. No tests deleted. Production LOC: 102162 -> 102162 (delta 0) Scope: all first-party product Rust, shipped SQL and JavaScript; core 38241, engine 56640, API 7281. Method: tools/production_loc.py --root SNAPSHOT --json on exact first-parent and staged-tree archives with the same counter; comments and all tests excluded. Exact trees and counter hash retained in registration artifacts/loc.json. Test/docs-only change. Reference absent (retired R9c; last counted 65,417 at tree 498dd1917812). --- core/docs/issues/463/FP21-FIX.md | 69 ++++++++++++++ .../tests/fp21_detach_stages.rs | 40 +++++++-- .../tests/support/fp21_read_pressure.rs | 89 +++++++++++++++++++ 3 files changed, 192 insertions(+), 6 deletions(-) create mode 100644 core/docs/issues/463/FP21-FIX.md create mode 100644 engine/crates/layerfs-daemon/tests/support/fp21_read_pressure.rs diff --git a/core/docs/issues/463/FP21-FIX.md b/core/docs/issues/463/FP21-FIX.md new file mode 100644 index 000000000..71e464d9e --- /dev/null +++ b/core/docs/issues/463/FP21-FIX.md @@ -0,0 +1,69 @@ +# FP-21 provider-read staging repair + +> **Status:** Dated planning checkpoint; not release evidence or a product contract. + +This test-only follow-up starts at migration commit `853abcbe2b`. The migration's +original FP-21 failure and verification exception remain recorded in +[IMPLEMENTATION.md](IMPLEMENTATION.md); this repair does not relabel that run. + +## Confirmed cause + +Both cases in +[fp21_detach_stages.rs](../../../../engine/crates/layerfs-daemon/tests/fp21_detach_stages.rs) +failed before their first Unmount, while waiting to hold a request in the +persistence provider. A diagnostic run reproduced both failures in 10.13 s: +OPEN had already answered `opened`, READDIR had answered the exact expected +names, active requests and gate holds were zero, and Storage reported many +pack-cache hits. The requests had completed without entering the armed gate. + +`Store::new(cache_bytes=0)` disables the shared canonical cache, not a mounted +reader's kept pack, decoded-group and pooled-value caches. The caller's +preparation (`lstat` or directory open) populated those caches. The old fixture +assumed every subsequent logical Store demand would reach persistence. + +## Repair + +The new external +[pressure helper](../../../../engine/crates/layerfs-daemon/tests/support/fp21_read_pressure.rs) +saves 73 valid inode leaves with 7,300 distinct inline metadata values and a real +saved payload. Their count derives from the existing 512 KiB pooled-value +allowance and 73-byte value width. Distinct mtimes prevent value deduplication. +After caller preparation quiesces, the helper reads those leaves through the +same mounted Workspace's ordinary Store ports, checking every canonical answer. +The existing cache-overflow path discards the prepared stored values. The +target request must acquire them again; its actual held provider call establishes +the staging condition. Pack and locator caches stay enabled, the Store policy +stays at its default, and the global persistence profile remains explicitly +Disposable. + +No production API, cache-reset hook, dependency, assertion or timeout changes. +No tests are deleted. A staging timeout now reports mount, gate, reader and +Storage counters plus any caller response. The existing checks still require +exactly one held request, ten Busy unmounts with no effect, unchanged ownership, +the original successful result after release, and complete subsequent cleanup. + +## Verification and retained evidence + +The first repaired run passed both cases in 0.25 s under a 90-second command +ceiling. Each case observed `active=1`, `holding=1`, `expired=0`, and unchanged +engine counts during ten Busy unmount attempts. OPEN then read the exact +3,000 bytes; READDIR returned the exact three names; both reached cleanup Gone. + +Focused Linux test compilation and warning-denying Clippy passed, as did Rust +formatting, the full boundary guard (954 production inputs), its 34 self-tests, +fuser provenance and whitespace checks. This is a scoped fixture repair; no +full migration suite, benchmark or Durable execution is repeated. + +Receipts are append-only outside Git under +`~/.cache/layerfs-worktrees/fix-fp21-provider-gate-194dabf32fd3/builds/`: + +- `diagnostic-6738cd312831423dae9c3ef6f2dd308d`: reproduced staging failures. +- `pooled-pressure-0b3b856f7a794ae6919249bd2f50810a`: first successful repair. +- `cargo-linux-df19d4d4e85744ca980aa39abce7668d`: focused Clippy. +- `final-proof-abaf6103a7b34fbd92f42694aaae37bc`: final focused proof, 2/2 passed. + +The final verification receipt and exact snapshot LOC comparison are retained +in the same registration. Production LOC: 102162 -> 102162 (delta 0), counted +with `tools/production_loc.py --json` on exact parent and staged trees. Core +38,241; engine 56,640; API 7,281. Reference absent (retired R9c; last counted +65,417 at tree `498dd1917812`). diff --git a/engine/crates/layerfs-daemon/tests/fp21_detach_stages.rs b/engine/crates/layerfs-daemon/tests/fp21_detach_stages.rs index 7c1ef7cff..3b8d39f09 100644 --- a/engine/crates/layerfs-daemon/tests/fp21_detach_stages.rs +++ b/engine/crates/layerfs-daemon/tests/fp21_detach_stages.rs @@ -14,8 +14,11 @@ //! 2. **OPEN** and 3. **READDIR inside a provider read.** The Store is //! composed from the public pieces `open_store` composes, with each read //! session's pack persistence port behind `support/store_gate.rs` and no -//! object cache. An external python3 process of the command identity looks -//! the file up (or opens the directory) while the gate is open, and makes +//! shared canonical cache. Bounded reads of distinct stored inode values +//! displace the mounted reader's prepared values before the gate is armed; +//! pack and locator caches remain enabled. An external python3 process of +//! the command identity looks the file up (or opens the directory) while +//! the gate is open, and makes //! its `open` (or its listing) after the test armed the gate: the request //! is held inside its reader's provider call. Both are synchronous kernel //! requests whose caller is blocked in its system call, so the product's @@ -49,6 +52,8 @@ mod model; #[allow(dead_code)] #[path = "support/mounted.rs"] mod mounted; +#[path = "support/fp21_read_pressure.rs"] +mod read_pressure; #[allow(dead_code)] #[path = "support/mounted_commit.rs"] mod rig; @@ -64,6 +69,7 @@ use layerfs_daemon::{ OwnerClient, }; use layerfs_fuse::request::Opcode; +use layerfs_history::HistoryCatalog; use layerfs_overlay::{CleanupState, KernelMount, KernelMountState, StoredCounts}; use layerfs_persistence::Handles; use layerfs_storage::{port::PackPersistence, ReservationBlocks, Storage}; @@ -389,7 +395,7 @@ impl Held { } } } -/// One mounted Workspace over a gated Store with no object cache, a helper +/// One mounted Workspace over a gated Store with no shared canonical cache, a helper /// Workspace bound beside it for the engine's daemon-wide counts, and one /// caller about to be held inside the Store read of its request. struct Staged { @@ -427,6 +433,15 @@ impl Staged { let config = || fixture.config.clone(); let writer = Handles::open_writable(config(), installed::BINDING, installed::CURSOR).unwrap(); + let scope = writer + .history + .branch_snapshot(fixture.branch) + .unwrap() + .unwrap() + .scope; + let producer = Storage::new(writer.storage.clone()).unwrap(); + let pressure = read_pressure::prepare(&producer); + drop(producer); let gate = Gate::new(); let reader_config = fixture.config.clone(); let reader_gate = gate.clone(); @@ -471,6 +486,7 @@ impl Staged { &Path::new(&ready.directory).join(held.target()), ); quiet(&harness, ready.token); + read_pressure::displace(&store, scope, ready.token.workspace, &pressure); let mount = engine_mount(&client, route).expect("attached engine mount"); let idle = engine_rows(&harness, ready.token); assert_eq!(idle.0.namespaces, empty.namespaces); @@ -573,10 +589,22 @@ fn unmount_beside(held: Held) { // The gate is armed, then the caller makes its one request. staged.gate.arm(); staged.caller().send(held.mode()); - within("the request is inside its Store read", || { + let deadline = Instant::now() + WAIT; + loop { let now = staged.work(); - staged.gate.observe().holding == 1 && now.active == 1 - }); + if staged.gate.observe().holding == 1 && now.active == 1 { + break; + } + assert!( + Instant::now() < deadline, + "NOT STAGED: {held:?}: mount={now:?} gate={:?} reads={:?} storage={:?} caller={:?}", + staged.gate.observe(), + staged.store.read_work(), + staged.store.reader_storage_diagnostics(2), + staged.caller().lines.try_recv() + ); + thread::sleep(Duration::from_millis(2)); + } let inside = staged.work(); let rows = engine_rows(&staged.harness, staged.ready.token); let readers = staged diff --git a/engine/crates/layerfs-daemon/tests/support/fp21_read_pressure.rs b/engine/crates/layerfs-daemon/tests/support/fp21_read_pressure.rs new file mode 100644 index 000000000..d31589fbb --- /dev/null +++ b/engine/crates/layerfs-daemon/tests/support/fp21_read_pressure.rs @@ -0,0 +1,89 @@ +//! Displace prepared inode values through the mounted reader's ordinary ports. +//! No namespace is changed and the fixture keeps the default Store policy. +use layerfs_content::{ + filesystem::attributes::PortableMetadata, + inode_leaf::{ + encode_inode_value, InodeKind, InodeLeaf, InodeLeafRow, InodeMetadata, InodeValue, + INODE_VALUE_BYTES, LEAF_ROW_BYTES, MAXIMUM_LEAF_ROWS, + }, + AuthenticatedObjects, FinalizedObject, ObjectId, ObjectRole, +}; +use layerfs_daemon::store::Store; +use layerfs_history::WorkspaceId; +use layerfs_storage::{policy::POOLED_VALUE_CACHE_BYTES, Storage}; +use std::sync::Arc; + +/// More distinct stored values than one reader can retain. Each leaf fits the +/// canonical grammar and each value references a real saved payload. Inline +/// mtimes make the values distinct, so persistence cannot deduplicate them. +pub fn prepare(storage: &Storage) -> Vec { + let payload = FinalizedObject::new( + ObjectRole::WholeFile, + layerfs_content::encode_whole_file_payload(b"FP-21 pressure").unwrap(), + ) + .unwrap(); + let save = storage.begin_save().unwrap(); + save.accept(payload.clone()).unwrap(); + let leaves = (POOLED_VALUE_CACHE_BYTES / INODE_VALUE_BYTES).div_ceil(MAXIMUM_LEAF_ROWS) + 1; + let objects = (0..leaves) + .map(|page| { + let rows = (0..MAXIMUM_LEAF_ROWS) + .map(|row| { + let serial = (page * MAXIMUM_LEAF_ROWS + row + 1) as u64; + InodeLeafRow { + serial, + value: encode_inode_value(InodeValue { + kind: InodeKind::RegularFile, + namespace_ref_count: 1, + content_root: payload.id(), + metadata_root: InodeMetadata::Inline(PortableMetadata { + mode: 0o644, + mtime_seconds: serial as i64, + mtime_nanoseconds: 0, + }), + }), + } + }) + .collect(); + let object = FinalizedObject::new( + ObjectRole::InodeLeaf, + InodeLeaf { + subtree_bytes: (MAXIMUM_LEAF_ROWS * LEAF_ROW_BYTES) as u64, + rows, + } + .encode() + .unwrap(), + ) + .unwrap(); + save.accept(object.clone()).unwrap(); + object + }) + .collect::>(); + save.finish().unwrap(); + objects +} + +/// Use this Workspace's reader, not the control reader or a new Storage handle. +/// The ordinary pooled-value cache clears on overflow. Subsequent reconstruction +/// of a prepared target must acquire its stored values again, even if its pack +/// body and locator remain resident. The actual gate hold proves that miss. +pub fn displace( + store: &Arc, + scope: ObjectId, + workspace: WorkspaceId, + objects: &[FinalizedObject], +) { + let ports = store.ports_for(scope, workspace); + for object in objects { + assert_eq!( + ports.read_canonical(object.id()).unwrap(), + object.canonical() + ); + } + println!( + "FP-21 displaced pooled values: {} leaves, {} distinct values, allowance={} bytes", + objects.len(), + objects.len() * MAXIMUM_LEAF_ROWS, + POOLED_VALUE_CACHE_BYTES + ); +} From b98ac4c2f7ad2b9498594bcfc8c6015dbe84dab8 Mon Sep 17 00:00:00 2001 From: YifanXu1999 Date: Tue, 27 Oct 2026 05:41:01 +0800 Subject: [PATCH 09/10] refactor(463): move the Rust out of api/ and flatten the packages api/ now holds only the published JavaScript packages; both Rust crates join the engine. Moves: - api/layerfs-api -> engine/crates/layerfs-api - api/binding -> engine/crates/layerfs-node (addon now builds at engine/crates/layerfs-node/layerfs.node) - api/agent/sdk -> api/agent - api/agent/cli -> api/cli - api/how-to-use -> api/docs api/backend, api/runtime, api/scripts and api/package.json stay. Relative and repository paths are rewritten in code, manifests, tests, skills, plugin install guides and maintained docs. Historical records (core/docs/issues, docs/versioned, docs/release-notes, docs/research) are left unchanged. Tooling follows the move: Cargo members are core/crates/* and engine/crates/*; the guard and the LOC counter classify layerfs-api and layerfs-node as engine by crate name, in both the old and new layouts; the sealed bundle (copy_sdk) mirrors the new api/ layout; CI path filters exclude engine/crates/layerfs-node (the binding stays outside CI); layer guides (root, engine, api AGENTS.md and api/README.md) updated. fixture_seal's scan roots drop the old api crate paths, now under engine. Verified: cargo metadata unchanged (15 packages, same edges/targets); cargo +1.85.1 check --workspace --all-targets and fmt --check pass; guard PASS (954 files, --skip-sdk 818); 155 Python tool tests pass; Ruff 0.17.2 format clean, no new lint findings; agent, backend, runtime, packaging (dispatch with the addon built at its new path), trace and exec_output stand-in tests pass; CLI 70/70. NOT_RUN on macOS: agent binary_write, init_refusals and reinit (Linux binding + Store needed). Deleted tests: none. Production LOC: 102162 -> 102162 (delta 0) Scope and method: tools/production_loc.py --root on git archive of the parent (ff7ccee2f6) and of the staged tree; per-file paths and counts match (954 files). Subtotals by the counter's name-based classification: core 38,241, engine 61,288, api 2,633. The parent's own counter recorded engine 56,640 / api 7,281; the difference is layerfs-api (1,913) and layerfs-node (2,735) reclassified to engine, a relocation, not a simplification. Reference absent (retired R9c; last counted 65,417 at tree 498dd1917812). Co-Authored-By: Claude Opus 5.5 --- .agents/skills/layerfs-js-sdk/SKILL.md | 10 +-- .../references/methods/sandbox.md | 2 +- .../layerfs-sdk-observe/references/tracing.md | 2 +- .github/workflows/ci.yml | 10 +-- .gitignore | 2 + AGENTS.md | 7 +- Cargo.toml | 2 - api/.gitignore | 1 - api/AGENTS.md | 26 +++---- api/README.md | 69 +++++++++--------- api/agent/{sdk => }/package.json | 0 .../{sdk => }/src/branch/diff_branches.js | 0 .../{sdk => }/src/branch/diff_commits.js | 0 api/agent/{sdk => }/src/branch/fork.js | 0 .../{sdk => }/src/branch/list_commits.js | 0 api/agent/{sdk => }/src/branch/merge.js | 0 api/agent/{sdk => }/src/branch/publish.js | 0 api/agent/{sdk => }/src/client.js | 0 api/agent/{sdk => }/src/errors.js | 0 api/agent/{sdk => }/src/fs/apply.js | 0 api/agent/{sdk => }/src/fs/blame.js | 0 api/agent/{sdk => }/src/fs/body.js | 0 api/agent/{sdk => }/src/fs/cp.js | 0 api/agent/{sdk => }/src/fs/diff_files.js | 0 api/agent/{sdk => }/src/fs/edit.js | 0 api/agent/{sdk => }/src/fs/glob.js | 0 api/agent/{sdk => }/src/fs/grep.js | 0 api/agent/{sdk => }/src/fs/index.js | 0 api/agent/{sdk => }/src/fs/list.js | 0 api/agent/{sdk => }/src/fs/mkdir.js | 0 api/agent/{sdk => }/src/fs/mv.js | 0 api/agent/{sdk => }/src/fs/read.js | 0 api/agent/{sdk => }/src/fs/rm.js | 0 api/agent/{sdk => }/src/fs/stat.js | 0 api/agent/{sdk => }/src/fs/write.js | 0 api/agent/{sdk => }/src/index.js | 0 api/agent/{sdk => }/src/internal.js | 0 api/agent/{sdk => }/src/names.js | 0 api/agent/{sdk => }/src/project/init.js | 0 .../{sdk => }/src/project/list_branches.js | 0 .../{sdk => }/src/project/list_sandboxes.js | 0 api/agent/{sdk => }/src/sandbox/close.js | 0 api/agent/{sdk => }/src/sandbox/create.js | 0 .../{sdk => }/src/sandbox/list_workspaces.js | 0 api/agent/{sdk => }/src/trace.js | 0 api/agent/{sdk => }/src/transport/frames.js | 0 api/agent/{sdk => }/src/transport/index.js | 0 .../{sdk => }/src/transport/inprocess.js | 4 +- .../{sdk => }/src/transport/worker_client.js | 0 api/agent/{sdk => }/src/workspace/commit.js | 0 api/agent/{sdk => }/src/workspace/exec.js | 0 api/agent/{sdk => }/src/workspace/mount.js | 0 api/agent/{sdk => }/src/workspace/unmount.js | 0 api/agent/{sdk => }/test/binary_write.mjs | 2 +- api/agent/{sdk => }/test/calls.mjs | 2 +- api/agent/{sdk => }/test/exec_output.mjs | 2 +- api/agent/{sdk => }/test/fixture/cases.mjs | 2 +- .../test/fixture/fake-docker-init.mjs | 0 .../{sdk => }/test/fixture/fake-native.cjs | 0 .../{sdk => }/test/fixture/fake-worker.mjs | 0 .../{sdk => }/test/fixture/spool-native.cjs | 2 +- .../{sdk => }/test/fixture/website/.gitignore | 0 .../{sdk => }/test/fixture/website/.npmrc | 0 .../{sdk => }/test/fixture/website/README.md | 0 .../test/fixture/website/app/layout.tsx | 0 .../test/fixture/website/app/page.tsx | 0 .../test/fixture/website/package-lock.json | 0 .../test/fixture/website/package.json | 0 .../fixture/website/packages/next/bin/next.js | 0 .../website/packages/next/package.json | 0 api/agent/{sdk => }/test/init_refusals.mjs | 2 +- api/agent/{sdk => }/test/packaging.mjs | 4 +- api/agent/{sdk => }/test/reinit.mjs | 2 +- api/agent/{sdk => }/test/trace.mjs | 2 +- .../{sdk => }/test/verify/calls_real.mjs | 4 +- .../test/verify/concurrent_unmount_real.mjs | 2 +- api/agent/{sdk => }/test/verify/container.mjs | 2 +- .../test/verify/daemon_host_real.mjs | 4 +- .../test/verify/direct_locking_real.mjs | 2 +- .../test/verify/direct_refusal_real.mjs | 2 +- .../test/verify/exec_mount_lookup_real.mjs | 2 +- .../test/verify/exec_output_real.mjs | 2 +- .../{sdk => }/test/verify/idle_close_real.mjs | 2 +- api/agent/{sdk => }/test/verify/reap_real.mjs | 2 +- .../test/verify/sandbox_image_real.mjs | 2 +- .../{sdk => }/test/verify/sandbox_real.mjs | 2 +- api/agent/{sdk => }/test/verify/scenario.mjs | 2 +- .../{sdk => }/test/verify/trace_real.mjs | 2 +- api/backend/test/backend.mjs | 2 +- api/binding/Cargo.toml | 29 -------- api/{agent => }/cli/.gitignore | 0 api/{agent => }/cli/package-lock.json | 6 +- api/{agent => }/cli/package.json | 2 +- api/{agent => }/cli/src/argv.js | 0 .../cli/src/branch/diff_branches.js | 0 .../cli/src/branch/diff_commits.js | 0 api/{agent => }/cli/src/branch/fork.js | 0 api/{agent => }/cli/src/branch/index.js | 0 .../cli/src/branch/list_commits.js | 0 api/{agent => }/cli/src/branch/merge.js | 0 api/{agent => }/cli/src/branch/publish.js | 0 api/{agent => }/cli/src/calls.js | 4 +- api/{agent => }/cli/src/common.js | 0 api/{agent => }/cli/src/fs/apply.js | 0 api/{agent => }/cli/src/fs/blame.js | 0 api/{agent => }/cli/src/fs/cp.js | 0 api/{agent => }/cli/src/fs/diff_files.js | 0 api/{agent => }/cli/src/fs/edit.js | 0 api/{agent => }/cli/src/fs/glob.js | 0 api/{agent => }/cli/src/fs/grep.js | 0 api/{agent => }/cli/src/fs/index.js | 0 api/{agent => }/cli/src/fs/list.js | 0 api/{agent => }/cli/src/fs/mkdir.js | 0 api/{agent => }/cli/src/fs/mv.js | 0 api/{agent => }/cli/src/fs/read.js | 0 api/{agent => }/cli/src/fs/rm.js | 0 api/{agent => }/cli/src/fs/stat.js | 0 api/{agent => }/cli/src/fs/write.js | 0 api/{agent => }/cli/src/help.js | 0 api/{agent => }/cli/src/layerfs.js | 0 api/{agent => }/cli/src/main.js | 0 api/{agent => }/cli/src/output.js | 0 api/{agent => }/cli/src/project/index.js | 0 api/{agent => }/cli/src/project/init.js | 0 .../cli/src/project/list_branches.js | 0 .../cli/src/project/list_sandboxes.js | 0 api/{agent => }/cli/src/sandbox/close.js | 0 api/{agent => }/cli/src/sandbox/create.js | 0 api/{agent => }/cli/src/sandbox/index.js | 0 .../cli/src/sandbox/list_workspaces.js | 0 api/{agent => }/cli/src/workspace/commit.js | 0 api/{agent => }/cli/src/workspace/exec.js | 0 api/{agent => }/cli/src/workspace/index.js | 0 api/{agent => }/cli/src/workspace/mount.js | 0 api/{agent => }/cli/src/workspace/unmount.js | 0 api/{agent => }/cli/test/cli.test.mjs | 18 ++--- api/{agent => }/cli/test/doc-tables.mjs | 6 +- api/{agent => }/cli/test/verify/cli_real.mjs | 6 +- api/{how-to-use => docs}/agent.md | 24 +++--- api/{how-to-use => docs}/backend.md | 4 +- api/{how-to-use => docs}/runtime.md | 0 api/layerfs-api/Cargo.toml | 29 -------- api/package.json | 4 +- api/runtime/src/platform/windows/index.js | 4 +- api/runtime/src/worker/server.js | 2 +- api/runtime/test/runtime.mjs | 6 +- api/scripts/build-native.mjs | 2 +- api/scripts/recover-records.mjs | 2 +- .../layerfs-content/tests/fixture_seal.rs | 3 +- core/docs/architecture/06-limits.md | 2 +- .../60-shared-store-foundation.md | 2 +- .../architecture/61-direct-store-adapter.md | 2 +- .../architecture/76-native-mount-session.md | 2 +- core/docs/architecture/82-sdk-call-channel.md | 12 +-- docs/README.md | 2 +- docs/general/parallel-worktrees.md | 4 +- docs/general/sdk.md | 24 +++--- engine/AGENTS.md | 14 +++- engine/crates/layerfs-api/Cargo.toml | 29 ++++++++ .../layerfs-api/examples/issue367_rm_probe.rs | 0 .../examples/sandbox_kernel_mount.rs | 0 .../layerfs-api/examples/sandbox_lifecycle.rs | 0 .../crates}/layerfs-api/src/base/args.rs | 0 .../crates}/layerfs-api/src/base/control.rs | 0 .../crates}/layerfs-api/src/base/dispatch.rs | 0 .../crates}/layerfs-api/src/base/failure.rs | 0 .../crates}/layerfs-api/src/base/internal.rs | 0 .../crates}/layerfs-api/src/base/mod.rs | 0 .../crates}/layerfs-api/src/base/recovery.rs | 0 .../crates}/layerfs-api/src/base/sdk.rs | 0 .../layerfs-api/src/branch/diff_branches.rs | 0 .../layerfs-api/src/branch/diff_commits.rs | 0 .../crates}/layerfs-api/src/branch/fork.rs | 0 .../layerfs-api/src/branch/list_commits.rs | 0 .../crates}/layerfs-api/src/branch/merge.rs | 0 .../crates}/layerfs-api/src/branch/mod.rs | 0 .../crates}/layerfs-api/src/branch/publish.rs | 0 .../crates}/layerfs-api/src/fs/apply.rs | 0 .../crates}/layerfs-api/src/fs/blame.rs | 0 .../crates}/layerfs-api/src/fs/cp.rs | 0 .../crates}/layerfs-api/src/fs/diff_files.rs | 0 .../crates}/layerfs-api/src/fs/edit.rs | 0 .../crates}/layerfs-api/src/fs/glob.rs | 0 .../crates}/layerfs-api/src/fs/grep.rs | 0 .../crates}/layerfs-api/src/fs/list.rs | 0 .../crates}/layerfs-api/src/fs/mkdir.rs | 0 .../crates}/layerfs-api/src/fs/mod.rs | 0 .../crates}/layerfs-api/src/fs/mv.rs | 0 .../crates}/layerfs-api/src/fs/read.rs | 0 .../crates}/layerfs-api/src/fs/rm.rs | 0 .../crates}/layerfs-api/src/fs/stat.rs | 0 .../crates}/layerfs-api/src/fs/write.rs | 0 {api => engine/crates}/layerfs-api/src/lib.rs | 0 .../crates}/layerfs-api/src/operator/call.rs | 0 .../layerfs-api/src/operator/inspect/mod.rs | 0 .../src/operator/inspect/snapshot.rs | 0 .../crates}/layerfs-api/src/operator/mod.rs | 0 .../layerfs-api/src/project/list_branches.rs | 0 .../crates}/layerfs-api/src/project/mod.rs | 0 .../crates}/layerfs-api/src/sandbox/close.rs | 0 .../crates}/layerfs-api/src/sandbox/commit.rs | 0 .../crates}/layerfs-api/src/sandbox/create.rs | 0 .../crates}/layerfs-api/src/sandbox/exec.rs | 0 .../crates}/layerfs-api/src/sandbox/mod.rs | 0 .../crates}/layerfs-api/src/sandbox/mount.rs | 0 .../crates}/layerfs-api/src/sandbox/status.rs | 0 .../layerfs-api/src/sandbox/unmount.rs | 0 .../crates}/layerfs-api/src/sandbox/values.rs | 0 .../layerfs-api/tests/concurrent_commits.rs | 0 .../crates}/layerfs-api/tests/diff_replay.rs | 0 .../crates}/layerfs-api/tests/diff_resume.rs | 0 .../tests/fixtures/merge-forms-root.sqlite | Bin .../layerfs-api/tests/golden/sdk_methods.txt | 0 .../tests/history_ancestry_oracle.rs | 0 .../layerfs-api/tests/history_diff_oracle.rs | 0 .../crates}/layerfs-api/tests/init.rs | 0 .../layerfs-api/tests/kernel_application.rs | 2 +- .../layerfs-api/tests/kernel_mount_routes.rs | 4 +- .../crates}/layerfs-api/tests/lane_merge.rs | 0 .../layerfs-api/tests/local_install.rs | 0 .../layerfs-api/tests/merge_by_serial.rs | 0 .../layerfs-api/tests/merge_forms_fixture.rs | 0 .../layerfs-api/tests/merge_metadata_only.rs | 0 .../layerfs-api/tests/merge_mixed_forms.rs | 0 .../crates}/layerfs-api/tests/merge_report.rs | 0 .../layerfs-api/tests/merge_root_oracle.rs | 0 .../crates}/layerfs-api/tests/merge_units.rs | 0 .../layerfs-api/tests/method_refusal_order.rs | 0 .../layerfs-api/tests/mount_control.rs | 6 +- .../layerfs-api/tests/observed_application.rs | 2 +- .../layerfs-api/tests/observed_control.rs | 0 .../layerfs-api/tests/operator_history.rs | 0 .../tests/r5_1_actual_daemon_commit.rs | 10 +-- .../layerfs-api/tests/refresh_lookups.rs | 0 .../layerfs-api/tests/relink_commit.rs | 0 .../layerfs-api/tests/replay_merges.rs | 0 .../layerfs-api/tests/sandbox_operations.rs | 2 +- .../layerfs-api/tests/scale_lineage_cap.rs | 0 .../layerfs-api/tests/sdk_branch_count.rs | 0 .../layerfs-api/tests/sdk_chunk_deltas.rs | 0 .../crates}/layerfs-api/tests/sdk_compare.rs | 0 .../layerfs-api/tests/sdk_diff_entries.rs | 0 .../layerfs-api/tests/sdk_diff_pages.rs | 0 .../layerfs-api/tests/sdk_diff_size.rs | 0 .../layerfs-api/tests/sdk_fixed_costs.rs | 0 .../layerfs-api/tests/sdk_fs_reads_replay.rs | 0 .../layerfs-api/tests/sdk_grep_reads.rs | 0 .../layerfs-api/tests/sdk_history_depth.rs | 0 .../layerfs-api/tests/sdk_list_entries.rs | 0 .../tests/sdk_merge_diagnostics.rs | 0 .../layerfs-api/tests/sdk_merge_paths.rs | 0 .../layerfs-api/tests/sdk_merge_scale.rs | 0 .../layerfs-api/tests/sdk_method_golden.rs | 0 .../layerfs-api/tests/sdk_mount_lookup.rs | 0 .../layerfs-api/tests/sdk_project_count.rs | 0 .../tests/sdk_reads_during_publish.rs | 0 .../tests/sdk_reads_under_publish.rs | 0 .../layerfs-api/tests/sdk_text_scan.rs | 0 .../layerfs-api/tests/sdk_timing_coverage.rs | 0 .../layerfs-api/tests/sdk_written_back.rs | 0 .../tests/support/daemon_binary.rs | 0 .../tests/support/installed_store.rs | 0 .../crates}/layerfs-api/tests/support/sdk.rs | 0 .../crates}/layerfs-api/tests/support/view.rs | 0 .../tests/workspace_reader_cache.rs | 0 .../crates}/layerfs-api/tests/write_cost.rs | 0 .../layerfs-api/tests/write_refusals.rs | 0 engine/crates/layerfs-node/Cargo.toml | 29 ++++++++ .../crates/layerfs-node}/build.rs | 0 .../layerfs-node}/examples/restore_record.rs | 0 .../crates/layerfs-node}/src/convert.rs | 0 .../crates/layerfs-node}/src/direct.rs | 0 .../crates/layerfs-node}/src/discovery.rs | 0 .../crates/layerfs-node}/src/dispatch.rs | 0 .../crates/layerfs-node}/src/exec.rs | 0 .../crates/layerfs-node}/src/job.rs | 0 .../crates/layerfs-node}/src/lib.rs | 0 .../crates/layerfs-node}/src/output.rs | 0 .../crates/layerfs-node}/src/pool.rs | 0 .../crates/layerfs-node}/src/project.rs | 0 .../crates/layerfs-node}/src/registry.rs | 0 .../crates/layerfs-node}/src/sandbox.rs | 0 .../crates/layerfs-node}/src/trace.rs | 0 .../crates/layerfs-node}/src/workspace.rs | 0 .../crates/layerfs-node}/tests/README.md | 0 .../layerfs-node}/tests/native_admission.rs | 0 .../layerfs-node}/tests/native_discovery.rs | 0 .../layerfs-node}/tests/support/engine.rs | 0 .../layerfs-node}/tests/support/fork_lock.c | 0 .../crates/layerfs-node}/tests/support/mod.rs | 0 plugins/dsh-layerfs/install.md | 2 +- plugins/magpie-layerfs/install.md | 4 +- tools/check_product_boundary.py | 20 ++--- tools/production_loc.py | 50 +++++++------ tools/test_check_product_boundary.py | 42 +++++++---- tools/test_ci_tests.py | 4 +- tools/test_production_loc.py | 51 ++++++++++--- tools/test_worktree.py | 38 +++++----- tools/worktree_build.py | 18 ++--- tools/worktree_resources.py | 10 +-- 300 files changed, 390 insertions(+), 337 deletions(-) rename api/agent/{sdk => }/package.json (100%) rename api/agent/{sdk => }/src/branch/diff_branches.js (100%) rename api/agent/{sdk => }/src/branch/diff_commits.js (100%) rename api/agent/{sdk => }/src/branch/fork.js (100%) rename api/agent/{sdk => }/src/branch/list_commits.js (100%) rename api/agent/{sdk => }/src/branch/merge.js (100%) rename api/agent/{sdk => }/src/branch/publish.js (100%) rename api/agent/{sdk => }/src/client.js (100%) rename api/agent/{sdk => }/src/errors.js (100%) rename api/agent/{sdk => }/src/fs/apply.js (100%) rename api/agent/{sdk => }/src/fs/blame.js (100%) rename api/agent/{sdk => }/src/fs/body.js (100%) rename api/agent/{sdk => }/src/fs/cp.js (100%) rename api/agent/{sdk => }/src/fs/diff_files.js (100%) rename api/agent/{sdk => }/src/fs/edit.js (100%) rename api/agent/{sdk => }/src/fs/glob.js (100%) rename api/agent/{sdk => }/src/fs/grep.js (100%) rename api/agent/{sdk => }/src/fs/index.js (100%) rename api/agent/{sdk => }/src/fs/list.js (100%) rename api/agent/{sdk => }/src/fs/mkdir.js (100%) rename api/agent/{sdk => }/src/fs/mv.js (100%) rename api/agent/{sdk => }/src/fs/read.js (100%) rename api/agent/{sdk => }/src/fs/rm.js (100%) rename api/agent/{sdk => }/src/fs/stat.js (100%) rename api/agent/{sdk => }/src/fs/write.js (100%) rename api/agent/{sdk => }/src/index.js (100%) rename api/agent/{sdk => }/src/internal.js (100%) rename api/agent/{sdk => }/src/names.js (100%) rename api/agent/{sdk => }/src/project/init.js (100%) rename api/agent/{sdk => }/src/project/list_branches.js (100%) rename api/agent/{sdk => }/src/project/list_sandboxes.js (100%) rename api/agent/{sdk => }/src/sandbox/close.js (100%) rename api/agent/{sdk => }/src/sandbox/create.js (100%) rename api/agent/{sdk => }/src/sandbox/list_workspaces.js (100%) rename api/agent/{sdk => }/src/trace.js (100%) rename api/agent/{sdk => }/src/transport/frames.js (100%) rename api/agent/{sdk => }/src/transport/index.js (100%) rename api/agent/{sdk => }/src/transport/inprocess.js (83%) rename api/agent/{sdk => }/src/transport/worker_client.js (100%) rename api/agent/{sdk => }/src/workspace/commit.js (100%) rename api/agent/{sdk => }/src/workspace/exec.js (100%) rename api/agent/{sdk => }/src/workspace/mount.js (100%) rename api/agent/{sdk => }/src/workspace/unmount.js (100%) rename api/agent/{sdk => }/test/binary_write.mjs (98%) rename api/agent/{sdk => }/test/calls.mjs (98%) rename api/agent/{sdk => }/test/exec_output.mjs (99%) rename api/agent/{sdk => }/test/fixture/cases.mjs (99%) rename api/agent/{sdk => }/test/fixture/fake-docker-init.mjs (100%) rename api/agent/{sdk => }/test/fixture/fake-native.cjs (100%) rename api/agent/{sdk => }/test/fixture/fake-worker.mjs (100%) rename api/agent/{sdk => }/test/fixture/spool-native.cjs (96%) rename api/agent/{sdk => }/test/fixture/website/.gitignore (100%) rename api/agent/{sdk => }/test/fixture/website/.npmrc (100%) rename api/agent/{sdk => }/test/fixture/website/README.md (100%) rename api/agent/{sdk => }/test/fixture/website/app/layout.tsx (100%) rename api/agent/{sdk => }/test/fixture/website/app/page.tsx (100%) rename api/agent/{sdk => }/test/fixture/website/package-lock.json (100%) rename api/agent/{sdk => }/test/fixture/website/package.json (100%) rename api/agent/{sdk => }/test/fixture/website/packages/next/bin/next.js (100%) rename api/agent/{sdk => }/test/fixture/website/packages/next/package.json (100%) rename api/agent/{sdk => }/test/init_refusals.mjs (99%) rename api/agent/{sdk => }/test/packaging.mjs (98%) rename api/agent/{sdk => }/test/reinit.mjs (98%) rename api/agent/{sdk => }/test/trace.mjs (99%) rename api/agent/{sdk => }/test/verify/calls_real.mjs (89%) rename api/agent/{sdk => }/test/verify/concurrent_unmount_real.mjs (96%) rename api/agent/{sdk => }/test/verify/container.mjs (98%) rename api/agent/{sdk => }/test/verify/daemon_host_real.mjs (97%) rename api/agent/{sdk => }/test/verify/direct_locking_real.mjs (98%) rename api/agent/{sdk => }/test/verify/direct_refusal_real.mjs (97%) rename api/agent/{sdk => }/test/verify/exec_mount_lookup_real.mjs (98%) rename api/agent/{sdk => }/test/verify/exec_output_real.mjs (98%) rename api/agent/{sdk => }/test/verify/idle_close_real.mjs (98%) rename api/agent/{sdk => }/test/verify/reap_real.mjs (97%) rename api/agent/{sdk => }/test/verify/sandbox_image_real.mjs (98%) rename api/agent/{sdk => }/test/verify/sandbox_real.mjs (98%) rename api/agent/{sdk => }/test/verify/scenario.mjs (99%) rename api/agent/{sdk => }/test/verify/trace_real.mjs (98%) delete mode 100644 api/binding/Cargo.toml rename api/{agent => }/cli/.gitignore (100%) rename api/{agent => }/cli/package-lock.json (84%) rename api/{agent => }/cli/package.json (91%) rename api/{agent => }/cli/src/argv.js (100%) rename api/{agent => }/cli/src/branch/diff_branches.js (100%) rename api/{agent => }/cli/src/branch/diff_commits.js (100%) rename api/{agent => }/cli/src/branch/fork.js (100%) rename api/{agent => }/cli/src/branch/index.js (100%) rename api/{agent => }/cli/src/branch/list_commits.js (100%) rename api/{agent => }/cli/src/branch/merge.js (100%) rename api/{agent => }/cli/src/branch/publish.js (100%) rename api/{agent => }/cli/src/calls.js (89%) rename api/{agent => }/cli/src/common.js (100%) rename api/{agent => }/cli/src/fs/apply.js (100%) rename api/{agent => }/cli/src/fs/blame.js (100%) rename api/{agent => }/cli/src/fs/cp.js (100%) rename api/{agent => }/cli/src/fs/diff_files.js (100%) rename api/{agent => }/cli/src/fs/edit.js (100%) rename api/{agent => }/cli/src/fs/glob.js (100%) rename api/{agent => }/cli/src/fs/grep.js (100%) rename api/{agent => }/cli/src/fs/index.js (100%) rename api/{agent => }/cli/src/fs/list.js (100%) rename api/{agent => }/cli/src/fs/mkdir.js (100%) rename api/{agent => }/cli/src/fs/mv.js (100%) rename api/{agent => }/cli/src/fs/read.js (100%) rename api/{agent => }/cli/src/fs/rm.js (100%) rename api/{agent => }/cli/src/fs/stat.js (100%) rename api/{agent => }/cli/src/fs/write.js (100%) rename api/{agent => }/cli/src/help.js (100%) rename api/{agent => }/cli/src/layerfs.js (100%) rename api/{agent => }/cli/src/main.js (100%) rename api/{agent => }/cli/src/output.js (100%) rename api/{agent => }/cli/src/project/index.js (100%) rename api/{agent => }/cli/src/project/init.js (100%) rename api/{agent => }/cli/src/project/list_branches.js (100%) rename api/{agent => }/cli/src/project/list_sandboxes.js (100%) rename api/{agent => }/cli/src/sandbox/close.js (100%) rename api/{agent => }/cli/src/sandbox/create.js (100%) rename api/{agent => }/cli/src/sandbox/index.js (100%) rename api/{agent => }/cli/src/sandbox/list_workspaces.js (100%) rename api/{agent => }/cli/src/workspace/commit.js (100%) rename api/{agent => }/cli/src/workspace/exec.js (100%) rename api/{agent => }/cli/src/workspace/index.js (100%) rename api/{agent => }/cli/src/workspace/mount.js (100%) rename api/{agent => }/cli/src/workspace/unmount.js (100%) rename api/{agent => }/cli/test/cli.test.mjs (94%) rename api/{agent => }/cli/test/doc-tables.mjs (86%) rename api/{agent => }/cli/test/verify/cli_real.mjs (95%) rename api/{how-to-use => docs}/agent.md (97%) rename api/{how-to-use => docs}/backend.md (98%) rename api/{how-to-use => docs}/runtime.md (100%) delete mode 100644 api/layerfs-api/Cargo.toml create mode 100644 engine/crates/layerfs-api/Cargo.toml rename {api => engine/crates}/layerfs-api/examples/issue367_rm_probe.rs (100%) rename {api => engine/crates}/layerfs-api/examples/sandbox_kernel_mount.rs (100%) rename {api => engine/crates}/layerfs-api/examples/sandbox_lifecycle.rs (100%) rename {api => engine/crates}/layerfs-api/src/base/args.rs (100%) rename {api => engine/crates}/layerfs-api/src/base/control.rs (100%) rename {api => engine/crates}/layerfs-api/src/base/dispatch.rs (100%) rename {api => engine/crates}/layerfs-api/src/base/failure.rs (100%) rename {api => engine/crates}/layerfs-api/src/base/internal.rs (100%) rename {api => engine/crates}/layerfs-api/src/base/mod.rs (100%) rename {api => engine/crates}/layerfs-api/src/base/recovery.rs (100%) rename {api => engine/crates}/layerfs-api/src/base/sdk.rs (100%) rename {api => engine/crates}/layerfs-api/src/branch/diff_branches.rs (100%) rename {api => engine/crates}/layerfs-api/src/branch/diff_commits.rs (100%) rename {api => engine/crates}/layerfs-api/src/branch/fork.rs (100%) rename {api => engine/crates}/layerfs-api/src/branch/list_commits.rs (100%) rename {api => engine/crates}/layerfs-api/src/branch/merge.rs (100%) rename {api => engine/crates}/layerfs-api/src/branch/mod.rs (100%) rename {api => engine/crates}/layerfs-api/src/branch/publish.rs (100%) rename {api => engine/crates}/layerfs-api/src/fs/apply.rs (100%) rename {api => engine/crates}/layerfs-api/src/fs/blame.rs (100%) rename {api => engine/crates}/layerfs-api/src/fs/cp.rs (100%) rename {api => engine/crates}/layerfs-api/src/fs/diff_files.rs (100%) rename {api => engine/crates}/layerfs-api/src/fs/edit.rs (100%) rename {api => engine/crates}/layerfs-api/src/fs/glob.rs (100%) rename {api => engine/crates}/layerfs-api/src/fs/grep.rs (100%) rename {api => engine/crates}/layerfs-api/src/fs/list.rs (100%) rename {api => engine/crates}/layerfs-api/src/fs/mkdir.rs (100%) rename {api => engine/crates}/layerfs-api/src/fs/mod.rs (100%) rename {api => engine/crates}/layerfs-api/src/fs/mv.rs (100%) rename {api => engine/crates}/layerfs-api/src/fs/read.rs (100%) rename {api => engine/crates}/layerfs-api/src/fs/rm.rs (100%) rename {api => engine/crates}/layerfs-api/src/fs/stat.rs (100%) rename {api => engine/crates}/layerfs-api/src/fs/write.rs (100%) rename {api => engine/crates}/layerfs-api/src/lib.rs (100%) rename {api => engine/crates}/layerfs-api/src/operator/call.rs (100%) rename {api => engine/crates}/layerfs-api/src/operator/inspect/mod.rs (100%) rename {api => engine/crates}/layerfs-api/src/operator/inspect/snapshot.rs (100%) rename {api => engine/crates}/layerfs-api/src/operator/mod.rs (100%) rename {api => engine/crates}/layerfs-api/src/project/list_branches.rs (100%) rename {api => engine/crates}/layerfs-api/src/project/mod.rs (100%) rename {api => engine/crates}/layerfs-api/src/sandbox/close.rs (100%) rename {api => engine/crates}/layerfs-api/src/sandbox/commit.rs (100%) rename {api => engine/crates}/layerfs-api/src/sandbox/create.rs (100%) rename {api => engine/crates}/layerfs-api/src/sandbox/exec.rs (100%) rename {api => engine/crates}/layerfs-api/src/sandbox/mod.rs (100%) rename {api => engine/crates}/layerfs-api/src/sandbox/mount.rs (100%) rename {api => engine/crates}/layerfs-api/src/sandbox/status.rs (100%) rename {api => engine/crates}/layerfs-api/src/sandbox/unmount.rs (100%) rename {api => engine/crates}/layerfs-api/src/sandbox/values.rs (100%) rename {api => engine/crates}/layerfs-api/tests/concurrent_commits.rs (100%) rename {api => engine/crates}/layerfs-api/tests/diff_replay.rs (100%) rename {api => engine/crates}/layerfs-api/tests/diff_resume.rs (100%) rename {api => engine/crates}/layerfs-api/tests/fixtures/merge-forms-root.sqlite (100%) rename {api => engine/crates}/layerfs-api/tests/golden/sdk_methods.txt (100%) rename {api => engine/crates}/layerfs-api/tests/history_ancestry_oracle.rs (100%) rename {api => engine/crates}/layerfs-api/tests/history_diff_oracle.rs (100%) rename {api => engine/crates}/layerfs-api/tests/init.rs (100%) rename {api => engine/crates}/layerfs-api/tests/kernel_application.rs (98%) rename {api => engine/crates}/layerfs-api/tests/kernel_mount_routes.rs (98%) rename {api => engine/crates}/layerfs-api/tests/lane_merge.rs (100%) rename {api => engine/crates}/layerfs-api/tests/local_install.rs (100%) rename {api => engine/crates}/layerfs-api/tests/merge_by_serial.rs (100%) rename {api => engine/crates}/layerfs-api/tests/merge_forms_fixture.rs (100%) rename {api => engine/crates}/layerfs-api/tests/merge_metadata_only.rs (100%) rename {api => engine/crates}/layerfs-api/tests/merge_mixed_forms.rs (100%) rename {api => engine/crates}/layerfs-api/tests/merge_report.rs (100%) rename {api => engine/crates}/layerfs-api/tests/merge_root_oracle.rs (100%) rename {api => engine/crates}/layerfs-api/tests/merge_units.rs (100%) rename {api => engine/crates}/layerfs-api/tests/method_refusal_order.rs (100%) rename {api => engine/crates}/layerfs-api/tests/mount_control.rs (99%) rename {api => engine/crates}/layerfs-api/tests/observed_application.rs (99%) rename {api => engine/crates}/layerfs-api/tests/observed_control.rs (100%) rename {api => engine/crates}/layerfs-api/tests/operator_history.rs (100%) rename {api => engine/crates}/layerfs-api/tests/r5_1_actual_daemon_commit.rs (97%) rename {api => engine/crates}/layerfs-api/tests/refresh_lookups.rs (100%) rename {api => engine/crates}/layerfs-api/tests/relink_commit.rs (100%) rename {api => engine/crates}/layerfs-api/tests/replay_merges.rs (100%) rename {api => engine/crates}/layerfs-api/tests/sandbox_operations.rs (99%) rename {api => engine/crates}/layerfs-api/tests/scale_lineage_cap.rs (100%) rename {api => engine/crates}/layerfs-api/tests/sdk_branch_count.rs (100%) rename {api => engine/crates}/layerfs-api/tests/sdk_chunk_deltas.rs (100%) rename {api => engine/crates}/layerfs-api/tests/sdk_compare.rs (100%) rename {api => engine/crates}/layerfs-api/tests/sdk_diff_entries.rs (100%) rename {api => engine/crates}/layerfs-api/tests/sdk_diff_pages.rs (100%) rename {api => engine/crates}/layerfs-api/tests/sdk_diff_size.rs (100%) rename {api => engine/crates}/layerfs-api/tests/sdk_fixed_costs.rs (100%) rename {api => engine/crates}/layerfs-api/tests/sdk_fs_reads_replay.rs (100%) rename {api => engine/crates}/layerfs-api/tests/sdk_grep_reads.rs (100%) rename {api => engine/crates}/layerfs-api/tests/sdk_history_depth.rs (100%) rename {api => engine/crates}/layerfs-api/tests/sdk_list_entries.rs (100%) rename {api => engine/crates}/layerfs-api/tests/sdk_merge_diagnostics.rs (100%) rename {api => engine/crates}/layerfs-api/tests/sdk_merge_paths.rs (100%) rename {api => engine/crates}/layerfs-api/tests/sdk_merge_scale.rs (100%) rename {api => engine/crates}/layerfs-api/tests/sdk_method_golden.rs (100%) rename {api => engine/crates}/layerfs-api/tests/sdk_mount_lookup.rs (100%) rename {api => engine/crates}/layerfs-api/tests/sdk_project_count.rs (100%) rename {api => engine/crates}/layerfs-api/tests/sdk_reads_during_publish.rs (100%) rename {api => engine/crates}/layerfs-api/tests/sdk_reads_under_publish.rs (100%) rename {api => engine/crates}/layerfs-api/tests/sdk_text_scan.rs (100%) rename {api => engine/crates}/layerfs-api/tests/sdk_timing_coverage.rs (100%) rename {api => engine/crates}/layerfs-api/tests/sdk_written_back.rs (100%) rename {api => engine/crates}/layerfs-api/tests/support/daemon_binary.rs (100%) rename {api => engine/crates}/layerfs-api/tests/support/installed_store.rs (100%) rename {api => engine/crates}/layerfs-api/tests/support/sdk.rs (100%) rename {api => engine/crates}/layerfs-api/tests/support/view.rs (100%) rename {api => engine/crates}/layerfs-api/tests/workspace_reader_cache.rs (100%) rename {api => engine/crates}/layerfs-api/tests/write_cost.rs (100%) rename {api => engine/crates}/layerfs-api/tests/write_refusals.rs (100%) create mode 100644 engine/crates/layerfs-node/Cargo.toml rename {api/binding => engine/crates/layerfs-node}/build.rs (100%) rename {api/binding => engine/crates/layerfs-node}/examples/restore_record.rs (100%) rename {api/binding => engine/crates/layerfs-node}/src/convert.rs (100%) rename {api/binding => engine/crates/layerfs-node}/src/direct.rs (100%) rename {api/binding => engine/crates/layerfs-node}/src/discovery.rs (100%) rename {api/binding => engine/crates/layerfs-node}/src/dispatch.rs (100%) rename {api/binding => engine/crates/layerfs-node}/src/exec.rs (100%) rename {api/binding => engine/crates/layerfs-node}/src/job.rs (100%) rename {api/binding => engine/crates/layerfs-node}/src/lib.rs (100%) rename {api/binding => engine/crates/layerfs-node}/src/output.rs (100%) rename {api/binding => engine/crates/layerfs-node}/src/pool.rs (100%) rename {api/binding => engine/crates/layerfs-node}/src/project.rs (100%) rename {api/binding => engine/crates/layerfs-node}/src/registry.rs (100%) rename {api/binding => engine/crates/layerfs-node}/src/sandbox.rs (100%) rename {api/binding => engine/crates/layerfs-node}/src/trace.rs (100%) rename {api/binding => engine/crates/layerfs-node}/src/workspace.rs (100%) rename {api/binding => engine/crates/layerfs-node}/tests/README.md (100%) rename {api/binding => engine/crates/layerfs-node}/tests/native_admission.rs (100%) rename {api/binding => engine/crates/layerfs-node}/tests/native_discovery.rs (100%) rename {api/binding => engine/crates/layerfs-node}/tests/support/engine.rs (100%) rename {api/binding => engine/crates/layerfs-node}/tests/support/fork_lock.c (100%) rename {api/binding => engine/crates/layerfs-node}/tests/support/mod.rs (100%) diff --git a/.agents/skills/layerfs-js-sdk/SKILL.md b/.agents/skills/layerfs-js-sdk/SKILL.md index c3852d5cf..f0a5bdabb 100644 --- a/.agents/skills/layerfs-js-sdk/SKILL.md +++ b/.agents/skills/layerfs-js-sdk/SKILL.md @@ -157,12 +157,12 @@ overwrite it. ## Import the SDK -The SDK is the `api/agent/sdk` folder of the LayerFS checkout. Link it into +The SDK is the `api/agent` folder of the LayerFS checkout. Link it into your folder once: ```bash npm init -y >/dev/null && npm pkg set type=module -npm install --no-audit --no-fund "file:$LAYERFS_REPO/api/agent/sdk" # LAYERFS_REPO: the LayerFS checkout +npm install --no-audit --no-fund "file:$LAYERFS_REPO/api/agent" # LAYERFS_REPO: the LayerFS checkout ``` Then, in any `.mjs` file: @@ -362,7 +362,7 @@ For Rust projects, follow the live-checked [Cargo workflow](references/rules/car ## Methods -Copied from [`api/how-to-use/agent.md`](../../../api/how-to-use/agent.md#methods), which is the source of truth. +Copied from [`api/docs/agent.md`](../../../api/docs/agent.md#methods), which is the source of truth. Every method is positional and returns a Promise. Each group's page has, for every method, its arguments, result fields, refusals with what to do, limits and examples. @@ -379,6 +379,6 @@ A `ref` is `main`, a Branch name, a Commit id or a Layer id. Paths are absolute view (`/src/index.js`). Pages are `{ items, hasMore }`; advance with `pagePos + items.length`. -Deeper material: the [SDK guide](../../../api/how-to-use/agent.md), the -[`layerfs` command](../../../api/how-to-use/agent.md#the-layerfs-command) and the +Deeper material: the [SDK guide](../../../api/docs/agent.md), the +[`layerfs` command](../../../api/docs/agent.md#the-layerfs-command) and the [0.1.7 SDK and UI guide](../../../docs/versioned/0.1.7/sdk-and-ui.md). diff --git a/.agents/skills/layerfs-js-sdk/references/methods/sandbox.md b/.agents/skills/layerfs-js-sdk/references/methods/sandbox.md index d731623ec..3899ea34b 100644 --- a/.agents/skills/layerfs-js-sdk/references/methods/sandbox.md +++ b/.agents/skills/layerfs-js-sdk/references/methods/sandbox.md @@ -2,7 +2,7 @@ > **Status:** Current general guide. Part of the `layerfs-js-sdk` skill. The methods > are #428's; behaviour is from the source and its Docker checks -> (`api/agent/sdk/test/verify/sandbox_real.mjs`). +> (`api/agent/test/verify/sandbox_real.mjs`). Examples use `layerfs` as connected in [SKILL.md](../../SKILL.md#connect-to-a-project). diff --git a/.agents/skills/layerfs-sdk-observe/references/tracing.md b/.agents/skills/layerfs-sdk-observe/references/tracing.md index 522e74f77..9423b1893 100644 --- a/.agents/skills/layerfs-sdk-observe/references/tracing.md +++ b/.agents/skills/layerfs-sdk-observe/references/tracing.md @@ -2,7 +2,7 @@ > **Status:** Current general guide. Part of the `layerfs-sdk-observe` skill. Describes the > #333 trace, merged to `main` in `62b225766`. Its source of truth is the call trace -> section of [`api/how-to-use/backend.md`](../../../../api/how-to-use/backend.md#the-call-trace). +> section of [`api/docs/backend.md`](../../../../api/docs/backend.md#the-call-trace). ## Turning it on diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 46e35450f..bad85750f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,9 +1,9 @@ # Fast lane: runs after a push and reports. It is never a required check and # never blocks a push or merge; agents do not wait for it (AGENTS.md §4). # Slow and FUSE mount tests run in nightly.yml. Selection: tools/ci_tests.py. -# The Node binding and JavaScript packages stay outside CI (owner, 2026-10-23): -# no path trigger, excluded from Clippy/tests and skipped by the guard. -# The Rust layerfs-api crate remains included at its relocated path. +# The Node binding (engine/crates/layerfs-node) and the JavaScript packages in +# api/ stay outside CI (owner, 2026-10-23): no path trigger, excluded from +# Clippy/tests and skipped by the guard. The Rust layerfs-api crate is included. name: ci on: @@ -12,7 +12,7 @@ on: paths: - "core/**" - "engine/**" - - "api/layerfs-api/**" + - "!engine/crates/layerfs-node/**" - "Cargo.*" - ".config/**" - "tools/**" @@ -24,7 +24,7 @@ on: paths: - "core/**" - "engine/**" - - "api/layerfs-api/**" + - "!engine/crates/layerfs-node/**" - "Cargo.*" - ".config/**" - "tools/**" diff --git a/.gitignore b/.gitignore index 6d259e61e..70c937bd2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ target/ +# The Node addon that api/scripts/build-native.mjs builds beside its crate. +/engine/crates/layerfs-node/layerfs.node /target-linux/ /eval/runs/ /eval/datasets/ diff --git a/AGENTS.md b/AGENTS.md index a48027e90..10c731048 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -455,8 +455,9 @@ Historical explanation is retained outside default implementation routing. All product layers follow the detailed [production source rules](engine/AGENTS.md#production-file-size-and-responsibility) and [checks and completion rules](engine/AGENTS.md#checks-and-completion). -The root manifest builds four core crates, nine engine crates, `layerfs-api` -and the Node binding. The dependency direction is `core < engine < api`, including -dev dependencies and test includes. Workstream names do not change this layering. +The root manifest builds four core crates and eleven engine crates, including +the SDK method surface `layerfs-api` and the Node binding `layerfs-node`; `api/` +holds the published JavaScript packages. The dependency direction is +`core < engine < api`, including dev dependencies and test includes. Workstream names do not change this layering. After rebasing across #463, update each selected worktree's own target registration and prepare again for the root `target/` path; never migrate another worktree's resource record. diff --git a/Cargo.toml b/Cargo.toml index a5ce75470..4aaba1281 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,8 +5,6 @@ resolver = "2" members = [ "core/crates/*", "engine/crates/*", - "api/layerfs-api", - "api/binding", ] exclude = [ "engine/vendor/fuser-0.18.0", diff --git a/api/.gitignore b/api/.gitignore index 30a8835c8..c2658d7d1 100644 --- a/api/.gitignore +++ b/api/.gitignore @@ -1,2 +1 @@ -binding/layerfs.node node_modules/ diff --git a/api/AGENTS.md b/api/AGENTS.md index 6b55bd674..6ab8e49ca 100644 --- a/api/AGENTS.md +++ b/api/AGENTS.md @@ -2,22 +2,18 @@ > **Status:** Current general guide. -Read [repository instructions](../AGENTS.md) first. This layer contains -`layerfs-api`, the Node binding (`layerfs-node` under `binding/`) and the -JavaScript packages. The [root Cargo manifest](../Cargo.toml) and -[SDK guide](../docs/general/sdk.md) establish the built Rust members and public -surface. API may depend on engine and core; dependencies and test source includes -from either lower layer back into API are forbidden. +Read [repository instructions](../AGENTS.md) first. This layer holds the +published JavaScript packages only, one folder each: `agent` (@layerfs/agent), +`cli` (@layerfs/cli), `backend` (@layerfs/backend) and `runtime` +(@layerfs/runtime), with their guides in `docs/` and the build scripts in +`scripts/`. It holds no Rust: the SDK method surface `layerfs-api` and the Node +binding `layerfs-node` are engine crates (see the +[engine guide](../engine/AGENTS.md#scope-and-ownership)); `scripts/build-native.mjs` +builds the addon beside its crate at `engine/crates/layerfs-node/layerfs.node`. +The packages load the engine through that addon or the worker; nothing in core +or engine may depend on them. -Project Store Init and install belong to `layerfs-project::store`; the Rust API -retains its public re-exports and the binding makes one direct Project Init call. -SDK-facing daemon integration tests live in `layerfs-api/tests`, with cheap -includes of lower-layer daemon fixtures. Build the ordinary daemon binary before -running tests that launch it. `LAYERFS_TEST_DAEMON` may select an explicit binary; -otherwise the tests locate the sibling Cargo output. The native binding's -[external proof guide](binding/tests/README.md) describes its Linux addon tests. - -All API product code follows the +All API product code, and the engine crates it loads, follow the [production size and responsibility rules](../engine/AGENTS.md#production-file-size-and-responsibility) and [checks and completion rules](../engine/AGENTS.md#checks-and-completion), including bounded test commands, build-before-run, locked dependencies, ARM64 diff --git a/api/README.md b/api/README.md index ea6623d54..b10f5d566 100644 --- a/api/README.md +++ b/api/README.md @@ -8,51 +8,54 @@ This is the wiki for `api/`, LayerFS's JavaScript packages: what each one is for, which one you need, and how they are built and tested. How to use each -one is in [`how-to-use/`](how-to-use): +one is in [`docs/`](docs): | Guide | Package | What it does | Who uses it | | --- | --- | --- | --- | -| [agent.md](how-to-use/agent.md) | `@layerfs/agent` and the `layerfs` command | Works on a project: files, Branches, Sandboxes, Workspaces, Exec and Commit | Agents, through a Node script (the SDK) or Bash (the command) | -| [backend.md](how-to-use/backend.md) | `@layerfs/backend` | Reads history, storage, Workspace state, background processes and daemon logs; the call trace | UIs and tools that show a project | -| [runtime.md](how-to-use/runtime.md) | `@layerfs/runtime` | Runs LayerFS on a machine: Init, project removal, the macOS and Windows worker, Sandbox and volume cleanup | Hosts that run projects for their users | +| [agent.md](docs/agent.md) | `@layerfs/agent` and the `layerfs` command | Works on a project: files, Branches, Sandboxes, Workspaces, Exec and Commit | Agents, through a Node script (the SDK) or Bash (the command) | +| [backend.md](docs/backend.md) | `@layerfs/backend` | Reads history, storage, Workspace state, background processes and daemon logs; the call trace | UIs and tools that show a project | +| [runtime.md](docs/runtime.md) | `@layerfs/runtime` | Runs LayerFS on a machine: Init, project removal, the macOS and Windows worker, Sandbox and volume cleanup | Hosts that run projects for their users | ## Which package do I need? -Every integration starts with [`@layerfs/agent`](how-to-use/agent.md) and adds +Every integration starts with [`@layerfs/agent`](docs/agent.md) and adds the others as it grows: - **A tool or skill for agents**, which works on a project's files and Branches: `@layerfs/agent`. Give agents that have only Bash - [the `layerfs` command](how-to-use/agent.md#the-layerfs-command). + [the `layerfs` command](docs/agent.md#the-layerfs-command). - **Something that shows a project**, such as a history view or a dashboard: - add [`@layerfs/backend`](how-to-use/backend.md), and read the - [call trace](how-to-use/backend.md#the-call-trace) to follow a run as it + add [`@layerfs/backend`](docs/backend.md), and read the + [call trace](docs/backend.md#the-call-trace) to follow a run as it happens. - **A host that runs projects for its users**, which initializes and removes them, and on macOS and Windows starts the worker: add - [`@layerfs/runtime`](how-to-use/runtime.md). + [`@layerfs/runtime`](docs/runtime.md). Store calls run in the calling process on Linux only. On macOS and Windows they go through the LayerFS home's worker, which `@layerfs/runtime` starts; see -[where calls run](how-to-use/agent.md#where-calls-run) and -[platforms and the worker](how-to-use/runtime.md#platforms-and-the-worker). +[where calls run](docs/agent.md#where-calls-run) and +[platforms and the worker](docs/runtime.md#platforms-and-the-worker). ## The folder -`api/` holds the JavaScript packages and the native addon: +`api/` holds the published JavaScript packages, one folder each, and no Rust: -- `agent/sdk/`: `@layerfs/agent`, the agents' SDK (the client, its +- `agent/`: `@layerfs/agent`, the agents' SDK (the client, its transports and the agent methods). -- `agent/cli/`: the `layerfs` command, one `@layerfs/agent` call per command. +- `cli/`: `@layerfs/cli`, the `layerfs` command, one `@layerfs/agent` call per command. - `backend/`: `@layerfs/backend`, per-project Store and daemon reads of an open client, for UIs and tools. - `runtime/`: `@layerfs/runtime`, installation management on a LayerFS home, for integrations. -- `binding/`: the Rust Node addon crate `layerfs-node` over core; it builds - `binding/layerfs.node`. -- `how-to-use/`: the three guides above. +- `docs/`: the three guides above. +- `scripts/`: `build-native.mjs` and `recover-records.mjs`. -`npm install` in `api` links `agent/sdk`, `backend` and `runtime` to each +The Rust behind them lives in the engine: the SDK method surface +`engine/crates/layerfs-api` and the Node addon crate +`engine/crates/layerfs-node`, which builds `engine/crates/layerfs-node/layerfs.node`. + +`npm install` in `api` links `agent`, `backend` and `runtime` to each other; it downloads nothing. `@layerfs/agent/internal` is not a public API. It exists only for @@ -86,18 +89,18 @@ Zombie reaping and the existing replaced-inode FUSE policy remain owner-deferred The stand-in tests need no Docker, Store or daemon: they load the real JavaScript over one stand-in native binding, -`agent/sdk/test/fixture/fake-native.cjs`, which the `layerfs` CLI tests +`agent/test/fixture/fake-native.cjs`, which the `layerfs` CLI tests use too. -- `node api/agent/sdk/test/calls.mjs` checks every agent call for +- `node api/agent/test/calls.mjs` checks every agent call for correctness against the shared case table - `agent/sdk/test/fixture/cases.mjs`. For each call it checks the binding + `agent/test/fixture/cases.mjs`. For each call it checks the binding call made, the arguments sent, and the result returned or the `LayerFSError` thrown. There is a case for every call file under - `agent/sdk/src/`. -- `node --test api/agent/cli/test/cli.test.mjs` runs the same cases through the SDK and + `agent/src/`. +- `node --test api/cli/test/cli.test.mjs` runs the same cases through the SDK and through the `layerfs` command and requires them to agree (see - [the `layerfs` command](how-to-use/agent.md#the-layerfs-command)). + [the `layerfs` command](docs/agent.md#the-layerfs-command)). - `packaging.mjs`, `trace.mjs`, `exec_output.mjs` and the backend and runtime tests each check one case per command (`node `). @@ -107,36 +110,36 @@ history) and `workspace` (a Sandbox, one Workspace, Exec, Commit and close). Run each part under the E2E launcher (`tools/worktree.py run`, see `docs/general/parallel-worktrees.md`): -- `node api/agent/sdk/test/verify/calls_real.mjs inner ` runs the +- `node api/agent/test/verify/calls_real.mjs inner ` runs the part through the SDK and checks each answer. -- `node api/agent/cli/test/verify/cli_real.mjs inner ` runs it through the SDK and +- `node api/cli/test/verify/cli_real.mjs inner ` runs it through the SDK and then as `layerfs` commands, and requires the same answers. Values that differ between any two runs are masked before the comparison. ### The `layerfs` command's tests ```bash -npm --prefix api/agent/cli install -node --test api/agent/cli/test/cli.test.mjs +npm --prefix api/cli install +node --test api/cli/test/cli.test.mjs ``` The tests run the real `@layerfs/agent` JavaScript over the stand-in native binding that the SDK's own tests use -(`api/agent/sdk/test/fixture/fake-native.cjs`). The binding records +(`api/agent/test/fixture/fake-native.cjs`). The binding records every call, so the tests need no Docker, Store or daemon. The SDK's `calls.mjs` checks the SDK for correctness against the shared case table -(`api/agent/sdk/test/fixture/cases.mjs`). These tests check that the +(`api/agent/test/fixture/cases.mjs`). These tests check that the command is consistent with the SDK. Each case runs through the SDK in the test's own process and through `layerfs`. The command must make the same binding call with the same arguments, then either print the SDK's result as JSON (`workspace mount` adds `ws`) and exit 0, or exit 125 with the SDK's refusal. The tests also check parsing, bodies, `--text`, `--stream` and exit -codes, that every call in the table has a case, and that `api/agent/cli/src` has a +codes, that every call in the table has a case, and that `api/cli/src` has a command file for every SDK call file. -`api/agent/cli/test/verify/cli_real.mjs inner ` checks the command +`api/cli/test/verify/cli_real.mjs inner ` checks the command against a real Store, Docker and daemon, under the E2E launcher. It runs the -SDK's real-Store scenario (`api/agent/sdk/test/verify/scenario.mjs`, +SDK's real-Store scenario (`api/agent/test/verify/scenario.mjs`, every call once) through the SDK and then as `layerfs` commands, one process per call. Each command must give the SDK's answer. The comparison masks only what differs between any two runs: the project name, object ids, times, inode diff --git a/api/agent/sdk/package.json b/api/agent/package.json similarity index 100% rename from api/agent/sdk/package.json rename to api/agent/package.json diff --git a/api/agent/sdk/src/branch/diff_branches.js b/api/agent/src/branch/diff_branches.js similarity index 100% rename from api/agent/sdk/src/branch/diff_branches.js rename to api/agent/src/branch/diff_branches.js diff --git a/api/agent/sdk/src/branch/diff_commits.js b/api/agent/src/branch/diff_commits.js similarity index 100% rename from api/agent/sdk/src/branch/diff_commits.js rename to api/agent/src/branch/diff_commits.js diff --git a/api/agent/sdk/src/branch/fork.js b/api/agent/src/branch/fork.js similarity index 100% rename from api/agent/sdk/src/branch/fork.js rename to api/agent/src/branch/fork.js diff --git a/api/agent/sdk/src/branch/list_commits.js b/api/agent/src/branch/list_commits.js similarity index 100% rename from api/agent/sdk/src/branch/list_commits.js rename to api/agent/src/branch/list_commits.js diff --git a/api/agent/sdk/src/branch/merge.js b/api/agent/src/branch/merge.js similarity index 100% rename from api/agent/sdk/src/branch/merge.js rename to api/agent/src/branch/merge.js diff --git a/api/agent/sdk/src/branch/publish.js b/api/agent/src/branch/publish.js similarity index 100% rename from api/agent/sdk/src/branch/publish.js rename to api/agent/src/branch/publish.js diff --git a/api/agent/sdk/src/client.js b/api/agent/src/client.js similarity index 100% rename from api/agent/sdk/src/client.js rename to api/agent/src/client.js diff --git a/api/agent/sdk/src/errors.js b/api/agent/src/errors.js similarity index 100% rename from api/agent/sdk/src/errors.js rename to api/agent/src/errors.js diff --git a/api/agent/sdk/src/fs/apply.js b/api/agent/src/fs/apply.js similarity index 100% rename from api/agent/sdk/src/fs/apply.js rename to api/agent/src/fs/apply.js diff --git a/api/agent/sdk/src/fs/blame.js b/api/agent/src/fs/blame.js similarity index 100% rename from api/agent/sdk/src/fs/blame.js rename to api/agent/src/fs/blame.js diff --git a/api/agent/sdk/src/fs/body.js b/api/agent/src/fs/body.js similarity index 100% rename from api/agent/sdk/src/fs/body.js rename to api/agent/src/fs/body.js diff --git a/api/agent/sdk/src/fs/cp.js b/api/agent/src/fs/cp.js similarity index 100% rename from api/agent/sdk/src/fs/cp.js rename to api/agent/src/fs/cp.js diff --git a/api/agent/sdk/src/fs/diff_files.js b/api/agent/src/fs/diff_files.js similarity index 100% rename from api/agent/sdk/src/fs/diff_files.js rename to api/agent/src/fs/diff_files.js diff --git a/api/agent/sdk/src/fs/edit.js b/api/agent/src/fs/edit.js similarity index 100% rename from api/agent/sdk/src/fs/edit.js rename to api/agent/src/fs/edit.js diff --git a/api/agent/sdk/src/fs/glob.js b/api/agent/src/fs/glob.js similarity index 100% rename from api/agent/sdk/src/fs/glob.js rename to api/agent/src/fs/glob.js diff --git a/api/agent/sdk/src/fs/grep.js b/api/agent/src/fs/grep.js similarity index 100% rename from api/agent/sdk/src/fs/grep.js rename to api/agent/src/fs/grep.js diff --git a/api/agent/sdk/src/fs/index.js b/api/agent/src/fs/index.js similarity index 100% rename from api/agent/sdk/src/fs/index.js rename to api/agent/src/fs/index.js diff --git a/api/agent/sdk/src/fs/list.js b/api/agent/src/fs/list.js similarity index 100% rename from api/agent/sdk/src/fs/list.js rename to api/agent/src/fs/list.js diff --git a/api/agent/sdk/src/fs/mkdir.js b/api/agent/src/fs/mkdir.js similarity index 100% rename from api/agent/sdk/src/fs/mkdir.js rename to api/agent/src/fs/mkdir.js diff --git a/api/agent/sdk/src/fs/mv.js b/api/agent/src/fs/mv.js similarity index 100% rename from api/agent/sdk/src/fs/mv.js rename to api/agent/src/fs/mv.js diff --git a/api/agent/sdk/src/fs/read.js b/api/agent/src/fs/read.js similarity index 100% rename from api/agent/sdk/src/fs/read.js rename to api/agent/src/fs/read.js diff --git a/api/agent/sdk/src/fs/rm.js b/api/agent/src/fs/rm.js similarity index 100% rename from api/agent/sdk/src/fs/rm.js rename to api/agent/src/fs/rm.js diff --git a/api/agent/sdk/src/fs/stat.js b/api/agent/src/fs/stat.js similarity index 100% rename from api/agent/sdk/src/fs/stat.js rename to api/agent/src/fs/stat.js diff --git a/api/agent/sdk/src/fs/write.js b/api/agent/src/fs/write.js similarity index 100% rename from api/agent/sdk/src/fs/write.js rename to api/agent/src/fs/write.js diff --git a/api/agent/sdk/src/index.js b/api/agent/src/index.js similarity index 100% rename from api/agent/sdk/src/index.js rename to api/agent/src/index.js diff --git a/api/agent/sdk/src/internal.js b/api/agent/src/internal.js similarity index 100% rename from api/agent/sdk/src/internal.js rename to api/agent/src/internal.js diff --git a/api/agent/sdk/src/names.js b/api/agent/src/names.js similarity index 100% rename from api/agent/sdk/src/names.js rename to api/agent/src/names.js diff --git a/api/agent/sdk/src/project/init.js b/api/agent/src/project/init.js similarity index 100% rename from api/agent/sdk/src/project/init.js rename to api/agent/src/project/init.js diff --git a/api/agent/sdk/src/project/list_branches.js b/api/agent/src/project/list_branches.js similarity index 100% rename from api/agent/sdk/src/project/list_branches.js rename to api/agent/src/project/list_branches.js diff --git a/api/agent/sdk/src/project/list_sandboxes.js b/api/agent/src/project/list_sandboxes.js similarity index 100% rename from api/agent/sdk/src/project/list_sandboxes.js rename to api/agent/src/project/list_sandboxes.js diff --git a/api/agent/sdk/src/sandbox/close.js b/api/agent/src/sandbox/close.js similarity index 100% rename from api/agent/sdk/src/sandbox/close.js rename to api/agent/src/sandbox/close.js diff --git a/api/agent/sdk/src/sandbox/create.js b/api/agent/src/sandbox/create.js similarity index 100% rename from api/agent/sdk/src/sandbox/create.js rename to api/agent/src/sandbox/create.js diff --git a/api/agent/sdk/src/sandbox/list_workspaces.js b/api/agent/src/sandbox/list_workspaces.js similarity index 100% rename from api/agent/sdk/src/sandbox/list_workspaces.js rename to api/agent/src/sandbox/list_workspaces.js diff --git a/api/agent/sdk/src/trace.js b/api/agent/src/trace.js similarity index 100% rename from api/agent/sdk/src/trace.js rename to api/agent/src/trace.js diff --git a/api/agent/sdk/src/transport/frames.js b/api/agent/src/transport/frames.js similarity index 100% rename from api/agent/sdk/src/transport/frames.js rename to api/agent/src/transport/frames.js diff --git a/api/agent/sdk/src/transport/index.js b/api/agent/src/transport/index.js similarity index 100% rename from api/agent/sdk/src/transport/index.js rename to api/agent/src/transport/index.js diff --git a/api/agent/sdk/src/transport/inprocess.js b/api/agent/src/transport/inprocess.js similarity index 83% rename from api/agent/sdk/src/transport/inprocess.js rename to api/agent/src/transport/inprocess.js index 65a69af32..6d8989530 100644 --- a/api/agent/sdk/src/transport/inprocess.js +++ b/api/agent/src/transport/inprocess.js @@ -1,5 +1,5 @@ // The in-process transport: the real native addon in this process, from -// LAYERFS_NATIVE, else api/binding/layerfs.node. Store calls open the +// LAYERFS_NATIVE, else engine/crates/layerfs-node/layerfs.node. Store calls open the // project's Store here (Linux only, #352 F-020). import { createRequire } from "node:module"; import { fileURLToPath } from "node:url"; @@ -15,7 +15,7 @@ export const WORKERS = 64; process.env.UV_THREADPOOL_SIZE ??= String(WORKERS); /** The addon file this process loads. */ -export const addonPath = () => process.env.LAYERFS_NATIVE || fileURLToPath(new URL("../../../../binding/layerfs.node", import.meta.url)); +export const addonPath = () => process.env.LAYERFS_NATIVE || fileURLToPath(new URL("../../../../engine/crates/layerfs-node/layerfs.node", import.meta.url)); /** The loaded addon. */ export const inprocess = () => require(addonPath()); diff --git a/api/agent/sdk/src/transport/worker_client.js b/api/agent/src/transport/worker_client.js similarity index 100% rename from api/agent/sdk/src/transport/worker_client.js rename to api/agent/src/transport/worker_client.js diff --git a/api/agent/sdk/src/workspace/commit.js b/api/agent/src/workspace/commit.js similarity index 100% rename from api/agent/sdk/src/workspace/commit.js rename to api/agent/src/workspace/commit.js diff --git a/api/agent/sdk/src/workspace/exec.js b/api/agent/src/workspace/exec.js similarity index 100% rename from api/agent/sdk/src/workspace/exec.js rename to api/agent/src/workspace/exec.js diff --git a/api/agent/sdk/src/workspace/mount.js b/api/agent/src/workspace/mount.js similarity index 100% rename from api/agent/sdk/src/workspace/mount.js rename to api/agent/src/workspace/mount.js diff --git a/api/agent/sdk/src/workspace/unmount.js b/api/agent/src/workspace/unmount.js similarity index 100% rename from api/agent/sdk/src/workspace/unmount.js rename to api/agent/src/workspace/unmount.js diff --git a/api/agent/sdk/test/binary_write.mjs b/api/agent/test/binary_write.mjs similarity index 98% rename from api/agent/sdk/test/binary_write.mjs rename to api/agent/test/binary_write.mjs index 560f97840..9c1cd9356 100644 --- a/api/agent/sdk/test/binary_write.mjs +++ b/api/agent/test/binary_write.mjs @@ -3,7 +3,7 @@ // shared, detached and non-binary bodies before the call. Reads stay text // only. Real native binding, Disposable Store, no Docker or daemon; Linux, // with LAYERFS_STORE_PATH on a local volume (the E2E launcher's): -// node api/agent/sdk/test/binary_write.mjs +// node api/agent/test/binary_write.mjs import assert from "node:assert/strict"; import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; diff --git a/api/agent/sdk/test/calls.mjs b/api/agent/test/calls.mjs similarity index 98% rename from api/agent/sdk/test/calls.mjs rename to api/agent/test/calls.mjs index 02718c84d..838357fa7 100644 --- a/api/agent/sdk/test/calls.mjs +++ b/api/agent/test/calls.mjs @@ -2,7 +2,7 @@ // fixture/cases.mjs (shared with the `layerfs` CLI tests) makes its one // binding call with the expected arguments and returns the expected result, // or throws the expected LayerFSError. No Docker, Store or daemon: -// node api/agent/sdk/test/calls.mjs +// node api/agent/test/calls.mjs import assert from "node:assert/strict"; import { readdirSync } from "node:fs"; import { createRequire } from "node:module"; diff --git a/api/agent/sdk/test/exec_output.mjs b/api/agent/test/exec_output.mjs similarity index 99% rename from api/agent/sdk/test/exec_output.mjs rename to api/agent/test/exec_output.mjs index 132267c1b..64671b60a 100644 --- a/api/agent/sdk/test/exec_output.mjs +++ b/api/agent/test/exec_output.mjs @@ -1,5 +1,5 @@ // workspace.exec output delivery over a stand-in binding (no Docker): -// node api/agent/sdk/test/exec_output.mjs +// node api/agent/test/exec_output.mjs // A small result is returned as the binding gives it; a spooled stream is // read back into one reused window of at most 1 MiB, complete, then // released; sinks get raw bytes, one page after the last is written; a failed diff --git a/api/agent/sdk/test/fixture/cases.mjs b/api/agent/test/fixture/cases.mjs similarity index 99% rename from api/agent/sdk/test/fixture/cases.mjs rename to api/agent/test/fixture/cases.mjs index 3663b1c22..1ecd5d924 100644 --- a/api/agent/sdk/test/fixture/cases.mjs +++ b/api/agent/test/fixture/cases.mjs @@ -9,7 +9,7 @@ // LayerFSError it throws ({ code, message, detail }); a refusal the SDK // makes itself sends nothing (`op` null). // agent/test/calls.mjs checks the SDK against `sent` and `result` -// (correctness). api/agent/cli/test/cli.test.mjs runs each case through both and +// (correctness). api/cli/test/cli.test.mjs runs each case through both and // checks that the CLI sends and prints exactly what the SDK sends and // returns (consistency). const WS = { sandbox: "1", path: "/workspaces/w1" }; diff --git a/api/agent/sdk/test/fixture/fake-docker-init.mjs b/api/agent/test/fixture/fake-docker-init.mjs similarity index 100% rename from api/agent/sdk/test/fixture/fake-docker-init.mjs rename to api/agent/test/fixture/fake-docker-init.mjs diff --git a/api/agent/sdk/test/fixture/fake-native.cjs b/api/agent/test/fixture/fake-native.cjs similarity index 100% rename from api/agent/sdk/test/fixture/fake-native.cjs rename to api/agent/test/fixture/fake-native.cjs diff --git a/api/agent/sdk/test/fixture/fake-worker.mjs b/api/agent/test/fixture/fake-worker.mjs similarity index 100% rename from api/agent/sdk/test/fixture/fake-worker.mjs rename to api/agent/test/fixture/fake-worker.mjs diff --git a/api/agent/sdk/test/fixture/spool-native.cjs b/api/agent/test/fixture/spool-native.cjs similarity index 96% rename from api/agent/sdk/test/fixture/spool-native.cjs rename to api/agent/test/fixture/spool-native.cjs index 7e76d175b..e92d9bbc2 100644 --- a/api/agent/sdk/test/fixture/spool-native.cjs +++ b/api/agent/test/fixture/spool-native.cjs @@ -1,7 +1,7 @@ // A stand-in binding for workspace.exec output checks: no Docker or daemon. // `exports.outputs[command]` is `{ stdout, stderr }` Buffers; a stream over // INLINE bytes (or any non-empty stream with `spool`) is spooled and paged -// like the real binding (api/binding/src/output.rs) into the caller's +// like the real binding (engine/crates/layerfs-node/src/output.rs) into the caller's // page. `exports.failPage` refuses the next page read. const INLINE = 1 << 20; const PAGE = 1 << 20; diff --git a/api/agent/sdk/test/fixture/website/.gitignore b/api/agent/test/fixture/website/.gitignore similarity index 100% rename from api/agent/sdk/test/fixture/website/.gitignore rename to api/agent/test/fixture/website/.gitignore diff --git a/api/agent/sdk/test/fixture/website/.npmrc b/api/agent/test/fixture/website/.npmrc similarity index 100% rename from api/agent/sdk/test/fixture/website/.npmrc rename to api/agent/test/fixture/website/.npmrc diff --git a/api/agent/sdk/test/fixture/website/README.md b/api/agent/test/fixture/website/README.md similarity index 100% rename from api/agent/sdk/test/fixture/website/README.md rename to api/agent/test/fixture/website/README.md diff --git a/api/agent/sdk/test/fixture/website/app/layout.tsx b/api/agent/test/fixture/website/app/layout.tsx similarity index 100% rename from api/agent/sdk/test/fixture/website/app/layout.tsx rename to api/agent/test/fixture/website/app/layout.tsx diff --git a/api/agent/sdk/test/fixture/website/app/page.tsx b/api/agent/test/fixture/website/app/page.tsx similarity index 100% rename from api/agent/sdk/test/fixture/website/app/page.tsx rename to api/agent/test/fixture/website/app/page.tsx diff --git a/api/agent/sdk/test/fixture/website/package-lock.json b/api/agent/test/fixture/website/package-lock.json similarity index 100% rename from api/agent/sdk/test/fixture/website/package-lock.json rename to api/agent/test/fixture/website/package-lock.json diff --git a/api/agent/sdk/test/fixture/website/package.json b/api/agent/test/fixture/website/package.json similarity index 100% rename from api/agent/sdk/test/fixture/website/package.json rename to api/agent/test/fixture/website/package.json diff --git a/api/agent/sdk/test/fixture/website/packages/next/bin/next.js b/api/agent/test/fixture/website/packages/next/bin/next.js similarity index 100% rename from api/agent/sdk/test/fixture/website/packages/next/bin/next.js rename to api/agent/test/fixture/website/packages/next/bin/next.js diff --git a/api/agent/sdk/test/fixture/website/packages/next/package.json b/api/agent/test/fixture/website/packages/next/package.json similarity index 100% rename from api/agent/sdk/test/fixture/website/packages/next/package.json rename to api/agent/test/fixture/website/packages/next/package.json diff --git a/api/agent/sdk/test/init_refusals.mjs b/api/agent/test/init_refusals.mjs similarity index 99% rename from api/agent/sdk/test/init_refusals.mjs rename to api/agent/test/init_refusals.mjs index 7969fa181..57ed60d3e 100644 --- a/api/agent/sdk/test/init_refusals.mjs +++ b/api/agent/test/init_refusals.mjs @@ -11,7 +11,7 @@ // keeps it (owner 2026-10-23). Real native binding, // Disposable Store, no daemon; Linux as root, with LAYERFS_STORE_PATH on a // local volume (the E2E launcher's): -// node api/agent/sdk/test/init_refusals.mjs +// node api/agent/test/init_refusals.mjs import assert from "node:assert/strict"; import { execFileSync } from "node:child_process"; import { diff --git a/api/agent/sdk/test/packaging.mjs b/api/agent/test/packaging.mjs similarity index 98% rename from api/agent/sdk/test/packaging.mjs rename to api/agent/test/packaging.mjs index 05e538c71..496a616b9 100644 --- a/api/agent/sdk/test/packaging.mjs +++ b/api/agent/test/packaging.mjs @@ -1,8 +1,8 @@ // @layerfs/agent's surface and client lifecycle (#428). Each case is one // command; every case but `dispatch` uses the stand-in binding and creates no // Store: -// node api/agent/sdk/test/packaging.mjs surface|lifecycle|copy|sandbox|worker-route|transport-order|dispatch -// `dispatch` loads the real addon (LAYERFS_NATIVE or api/binding/layerfs.node). +// node api/agent/test/packaging.mjs surface|lifecycle|copy|sandbox|worker-route|transport-order|dispatch +// `dispatch` loads the real addon (LAYERFS_NATIVE or engine/crates/layerfs-node/layerfs.node). import assert from "node:assert/strict"; import { cpSync, mkdirSync, mkdtempSync, readFileSync, rmSync, symlinkSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; diff --git a/api/agent/sdk/test/reinit.mjs b/api/agent/test/reinit.mjs similarity index 98% rename from api/agent/sdk/test/reinit.mjs rename to api/agent/test/reinit.mjs index 92127b23d..e4b92b22c 100644 --- a/api/agent/sdk/test/reinit.mjs +++ b/api/agent/test/reinit.mjs @@ -5,7 +5,7 @@ // uses its own, as each Import uses a new volume. Real native binding, // Disposable Store, no Docker or daemon; Linux, with LAYERFS_STORE_PATH on a // local volume (the E2E launcher's): -// node api/agent/sdk/test/reinit.mjs +// node api/agent/test/reinit.mjs import assert from "node:assert/strict"; import { chmodSync, existsSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; diff --git a/api/agent/sdk/test/trace.mjs b/api/agent/test/trace.mjs similarity index 99% rename from api/agent/sdk/test/trace.mjs rename to api/agent/test/trace.mjs index daf72511d..bd43e47f9 100644 --- a/api/agent/sdk/test/trace.mjs +++ b/api/agent/test/trace.mjs @@ -1,5 +1,5 @@ // Per-call trace checks over a stand-in binding; each case is one command: -// node api/agent/sdk/test/trace.mjs on|off|failure|layerfs-env|start|ids|no-content|store|daemon-host +// node api/agent/test/trace.mjs on|off|failure|layerfs-env|start|ids|no-content|store|daemon-host // No Docker, Store or daemon is used. import assert from "node:assert/strict"; import { existsSync, mkdtempSync, readdirSync, readFileSync, rmSync } from "node:fs"; diff --git a/api/agent/sdk/test/verify/calls_real.mjs b/api/agent/test/verify/calls_real.mjs similarity index 89% rename from api/agent/sdk/test/verify/calls_real.mjs rename to api/agent/test/verify/calls_real.mjs index c5ac1fbae..d6c570043 100644 --- a/api/agent/sdk/test/verify/calls_real.mjs +++ b/api/agent/test/verify/calls_real.mjs @@ -2,8 +2,8 @@ // for correctness: one part of the shared scenario (scenario.mjs), each step // one SDK call made once on a fresh project. Disposable Store only. Under the // E2E launcher (its Store volume, deployment and sealed Linux bundle): -// node api/agent/sdk/test/verify/calls_real.mjs inner -// The `layerfs` command runs the same scenario in api/agent/cli/test/verify/cli_real.mjs. +// node api/agent/test/verify/calls_real.mjs inner +// The `layerfs` command runs the same scenario in api/cli/test/verify/cli_real.mjs. import { mkdtempSync, rmSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; diff --git a/api/agent/sdk/test/verify/concurrent_unmount_real.mjs b/api/agent/test/verify/concurrent_unmount_real.mjs similarity index 96% rename from api/agent/sdk/test/verify/concurrent_unmount_real.mjs rename to api/agent/test/verify/concurrent_unmount_real.mjs index 2a33f3d73..19c069e28 100644 --- a/api/agent/sdk/test/verify/concurrent_unmount_real.mjs +++ b/api/agent/test/verify/concurrent_unmount_real.mjs @@ -4,7 +4,7 @@ // step and its record step, and concurrent mounts take turns placing their // Workspaces in one Sandbox. Under the E2E launcher (its Store volume, home // and deployment): -// node api/agent/sdk/test/verify/concurrent_unmount_real.mjs inner +// node api/agent/test/verify/concurrent_unmount_real.mjs inner import assert from "node:assert/strict"; import { mkdtempSync, rmSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; diff --git a/api/agent/sdk/test/verify/container.mjs b/api/agent/test/verify/container.mjs similarity index 98% rename from api/agent/sdk/test/verify/container.mjs rename to api/agent/test/verify/container.mjs index f88d09324..59b24c198 100644 --- a/api/agent/sdk/test/verify/container.mjs +++ b/api/agent/test/verify/container.mjs @@ -8,7 +8,7 @@ import { spawnSync } from "node:child_process"; import { dirname, resolve } from "node:path"; import { fileURLToPath } from "node:url"; -export const REPO = resolve(dirname(fileURLToPath(import.meta.url)), "../../../../.."); +export const REPO = resolve(dirname(fileURLToPath(import.meta.url)), "../../../.."); export const RUNTIME = "layerfs-352-runtime:node24"; export const STORE_PATH = "/layerfs-store/global/store.sqlite"; diff --git a/api/agent/sdk/test/verify/daemon_host_real.mjs b/api/agent/test/verify/daemon_host_real.mjs similarity index 97% rename from api/agent/sdk/test/verify/daemon_host_real.mjs rename to api/agent/test/verify/daemon_host_real.mjs index 99c4fc15f..21939f4ff 100644 --- a/api/agent/sdk/test/verify/daemon_host_real.mjs +++ b/api/agent/test/verify/daemon_host_real.mjs @@ -4,7 +4,7 @@ // loopback, so the client dials LAYERFS_DAEMON_HOST (host.docker.internal on // Docker Desktop). The publish and its check are unchanged. // -// node api/agent/sdk/test/verify/daemon_host_real.mjs outer +// node api/agent/test/verify/daemon_host_real.mjs outer // // `outer` (on the Docker host) runs `inner` twice in the runtime image, each // in its own container with the Docker socket and a fresh volume of its own at @@ -20,7 +20,7 @@ import { dirname, join, resolve } from "node:path"; import { fileURLToPath } from "node:url"; const HERE = dirname(fileURLToPath(import.meta.url)); -const REPO = resolve(HERE, "../../../../.."); +const REPO = resolve(HERE, "../../../.."); const RUNTIME = "layerfs-352-runtime:node24"; const STORE = "/layerfs-store/global/store.sqlite"; const HOST = "host.docker.internal"; diff --git a/api/agent/sdk/test/verify/direct_locking_real.mjs b/api/agent/test/verify/direct_locking_real.mjs similarity index 98% rename from api/agent/sdk/test/verify/direct_locking_real.mjs rename to api/agent/test/verify/direct_locking_real.mjs index 052d1cb8f..d7887cd36 100644 --- a/api/agent/sdk/test/verify/direct_locking_real.mjs +++ b/api/agent/test/verify/direct_locking_real.mjs @@ -6,7 +6,7 @@ // publication succeed, `PRAGMA integrity_check` passes, and every Branch's // final tree equals a serial oracle built from the outcomes. // -// node api/agent/sdk/test/verify/direct_locking_real.mjs outer +// node api/agent/test/verify/direct_locking_real.mjs outer // // One attempt per call. The publishes start together (one Promise.all after // every Workspace is prepared), except daemonA.shared, released after diff --git a/api/agent/sdk/test/verify/direct_refusal_real.mjs b/api/agent/test/verify/direct_refusal_real.mjs similarity index 97% rename from api/agent/sdk/test/verify/direct_refusal_real.mjs rename to api/agent/test/verify/direct_refusal_real.mjs index 71efdf2e1..63897fb5e 100644 --- a/api/agent/sdk/test/verify/direct_refusal_real.mjs +++ b/api/agent/test/verify/direct_refusal_real.mjs @@ -6,7 +6,7 @@ // overlay directory is left. macOS is covered by // engine/crates/layerfs-store-service/tests/kernel_guard.rs. // -// node api/agent/sdk/test/verify/direct_refusal_real.mjs outer +// node api/agent/test/verify/direct_refusal_real.mjs outer import assert from "node:assert/strict"; import { execFileSync } from "node:child_process"; import { mkdirSync, mkdtempSync, readdirSync, readFileSync, rmSync, writeFileSync } from "node:fs"; diff --git a/api/agent/sdk/test/verify/exec_mount_lookup_real.mjs b/api/agent/test/verify/exec_mount_lookup_real.mjs similarity index 98% rename from api/agent/sdk/test/verify/exec_mount_lookup_real.mjs rename to api/agent/test/verify/exec_mount_lookup_real.mjs index 0ddaefcdc..12fbd1c78 100644 --- a/api/agent/sdk/test/verify/exec_mount_lookup_real.mjs +++ b/api/agent/test/verify/exec_mount_lookup_real.mjs @@ -1,7 +1,7 @@ // #352 F-029: a call that names a mount finds it in this process's mount table // and asks the daemon nothing about the Sandbox's other mounts. // -// node api/agent/sdk/test/verify/exec_mount_lookup_real.mjs outer +// node api/agent/test/verify/exec_mount_lookup_real.mjs outer // // `outer` (on the Docker host) makes a fresh Store volume and runs `inner` in // the runtime image. Process A starts Sandbox 1 (sandbox.create) and mounts four diff --git a/api/agent/sdk/test/verify/exec_output_real.mjs b/api/agent/test/verify/exec_output_real.mjs similarity index 98% rename from api/agent/sdk/test/verify/exec_output_real.mjs rename to api/agent/test/verify/exec_output_real.mjs index f2ddb63d8..0506ea75c 100644 --- a/api/agent/sdk/test/verify/exec_output_real.mjs +++ b/api/agent/test/verify/exec_output_real.mjs @@ -1,6 +1,6 @@ // #352 fix 056: a Sandbox exec's output arrives complete at any size. // -// node api/agent/sdk/test/verify/exec_output_real.mjs outer [check|time] +// node api/agent/test/verify/exec_output_real.mjs outer [check|time] // // `outer` (on the Docker host) makes a fresh Store volume and runs `inner` in // the runtime image, which is also the Sandbox image (it has Node). `check`: diff --git a/api/agent/sdk/test/verify/idle_close_real.mjs b/api/agent/test/verify/idle_close_real.mjs similarity index 98% rename from api/agent/sdk/test/verify/idle_close_real.mjs rename to api/agent/test/verify/idle_close_real.mjs index dd1a3608f..569cd04ac 100644 --- a/api/agent/sdk/test/verify/idle_close_real.mjs +++ b/api/agent/test/verify/idle_close_real.mjs @@ -6,7 +6,7 @@ // the Engine, which is what the daemon's own exit leaves; that exit is // checked by layerfs-daemon's observed_application test. Under the E2E // launcher (its Store volume, home and deployment): -// node api/agent/sdk/test/verify/idle_close_real.mjs inner +// node api/agent/test/verify/idle_close_real.mjs inner import assert from "node:assert/strict"; import { existsSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs"; import { request } from "node:http"; diff --git a/api/agent/sdk/test/verify/reap_real.mjs b/api/agent/test/verify/reap_real.mjs similarity index 97% rename from api/agent/sdk/test/verify/reap_real.mjs rename to api/agent/test/verify/reap_real.mjs index ac80c318b..a40853ded 100644 --- a/api/agent/sdk/test/verify/reap_real.mjs +++ b/api/agent/test/verify/reap_real.mjs @@ -5,7 +5,7 @@ // daemon still serves the Workspace, and the command's own exit status is // still its own. // -// node api/agent/sdk/test/verify/reap_real.mjs outer +// node api/agent/test/verify/reap_real.mjs outer // // `outer` (on the Docker host) makes a fresh Store volume and runs `inner` in // the runtime image, as the direct route needs (F-020). One attempt per step; diff --git a/api/agent/sdk/test/verify/sandbox_image_real.mjs b/api/agent/test/verify/sandbox_image_real.mjs similarity index 98% rename from api/agent/sdk/test/verify/sandbox_image_real.mjs rename to api/agent/test/verify/sandbox_image_real.mjs index 855808c8f..e9bc5d17b 100644 --- a/api/agent/sdk/test/verify/sandbox_image_real.mjs +++ b/api/agent/test/verify/sandbox_image_real.mjs @@ -6,7 +6,7 @@ // reuses its number. The second image is the deployment's with one label // (its own digest), built here through the Engine and deleted at the end. // Under the E2E launcher (its Store volume, home and deployment): -// node api/agent/sdk/test/verify/sandbox_image_real.mjs inner +// node api/agent/test/verify/sandbox_image_real.mjs inner import assert from "node:assert/strict"; import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs"; import { request } from "node:http"; diff --git a/api/agent/sdk/test/verify/sandbox_real.mjs b/api/agent/test/verify/sandbox_real.mjs similarity index 98% rename from api/agent/sdk/test/verify/sandbox_real.mjs rename to api/agent/test/verify/sandbox_real.mjs index 5406939de..ec7df2121 100644 --- a/api/agent/sdk/test/verify/sandbox_real.mjs +++ b/api/agent/test/verify/sandbox_real.mjs @@ -5,7 +5,7 @@ // messages naming the calls to make instead, and sandbox.close refuses // MountsActive, then stops it. Under the E2E launcher (its Store volume, // home and deployment): -// node api/agent/sdk/test/verify/sandbox_real.mjs inner +// node api/agent/test/verify/sandbox_real.mjs inner import assert from "node:assert/strict"; import { mkdtempSync, rmSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; diff --git a/api/agent/sdk/test/verify/scenario.mjs b/api/agent/test/verify/scenario.mjs similarity index 99% rename from api/agent/sdk/test/verify/scenario.mjs rename to api/agent/test/verify/scenario.mjs index 32b7e4c71..c96c5ffb2 100644 --- a/api/agent/sdk/test/verify/scenario.mjs +++ b/api/agent/test/verify/scenario.mjs @@ -10,7 +10,7 @@ // - `keep(result, ctx)` records what later steps name (commit ids, the // Workspace), so each run uses its own. // calls_real.mjs runs a part through the SDK and checks it (correctness); -// api/agent/cli/test/verify/cli_real.mjs runs it through the SDK and then the command +// api/cli/test/verify/cli_real.mjs runs it through the SDK and then the command // and requires the same answers, step by step (consistency). import assert from "node:assert/strict"; import { mkdirSync, writeFileSync } from "node:fs"; diff --git a/api/agent/sdk/test/verify/trace_real.mjs b/api/agent/test/verify/trace_real.mjs similarity index 98% rename from api/agent/sdk/test/verify/trace_real.mjs rename to api/agent/test/verify/trace_real.mjs index 1a8c1691f..7121c9727 100644 --- a/api/agent/sdk/test/verify/trace_real.mjs +++ b/api/agent/test/verify/trace_real.mjs @@ -1,7 +1,7 @@ // One real trace check on a Disposable Store: with LAYERFS_TRACE set, a fork, mount, exec, background process, Commit and merge write start and // end lines that carry their result ids and no file content. Under the E2E // launcher (its Store volume, home and deployment): -// node api/agent/sdk/test/verify/trace_real.mjs inner +// node api/agent/test/verify/trace_real.mjs inner import assert from "node:assert/strict"; import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; diff --git a/api/backend/test/backend.mjs b/api/backend/test/backend.mjs index 658a0656b..fa47c11f1 100644 --- a/api/backend/test/backend.mjs +++ b/api/backend/test/backend.mjs @@ -4,7 +4,7 @@ import assert from "node:assert/strict"; import { fileURLToPath } from "node:url"; -const FAKE = fileURLToPath(new URL("../../agent/sdk/test/fixture/fake-native.cjs", import.meta.url)); +const FAKE = fileURLToPath(new URL("../../agent/test/fixture/fake-native.cjs", import.meta.url)); Object.assign(process.env, { LAYERFS_NATIVE: FAKE, LAYERFS_HOME: "/private/home", LAYERFS_STORE_PATH: "/fake/store.sqlite" }); for (const name of ["TRACE", "TRACE_STEP", "TRACE_START", "WORKER_ENDPOINT"]) delete process.env[`LAYERFS_${name}`]; const { LayerFS, CODES } = await import("@layerfs/agent"); diff --git a/api/binding/Cargo.toml b/api/binding/Cargo.toml deleted file mode 100644 index 407396582..000000000 --- a/api/binding/Cargo.toml +++ /dev/null @@ -1,29 +0,0 @@ -[package] -name = "layerfs-node" -description = "Node binding for the LayerFS JavaScript SDK: Store calls in-process (layerfs-store-service), Sandbox calls over layerfs-api" -publish = false -workspace = "../.." -edition.workspace = true -version.workspace = true -rust-version.workspace = true -license.workspace = true - -[lib] -crate-type = ["cdylib"] -path = "src/lib.rs" - -[dependencies] -layerfs-project = { path = "../../engine/crates/layerfs-project" } -layerfs-api = { path = "../layerfs-api" } -layerfs-bridge = { path = "../../engine/crates/layerfs-bridge" } -layerfs-history = { path = "../../core/crates/layerfs-history" } -layerfs-persistence = { path = "../../engine/crates/layerfs-persistence" } -layerfs-sandbox = { path = "../../engine/crates/layerfs-sandbox" } -layerfs-storage = { path = "../../core/crates/layerfs-storage" } -layerfs-store-service = { path = "../../engine/crates/layerfs-store-service" } -layerfs-telemetry = { path = "../../core/crates/layerfs-telemetry" } -napi = "=2.16.17" -napi-derive = "=2.16.13" - -[build-dependencies] -napi-build = "=2.1.6" diff --git a/api/agent/cli/.gitignore b/api/cli/.gitignore similarity index 100% rename from api/agent/cli/.gitignore rename to api/cli/.gitignore diff --git a/api/agent/cli/package-lock.json b/api/cli/package-lock.json similarity index 84% rename from api/agent/cli/package-lock.json rename to api/cli/package-lock.json index d5a0fbef5..a0d51cd44 100644 --- a/api/agent/cli/package-lock.json +++ b/api/cli/package-lock.json @@ -8,7 +8,7 @@ "name": "@layerfs/cli", "version": "1.1.0", "dependencies": { - "@layerfs/agent": "file:../sdk" + "@layerfs/agent": "file:../agent" }, "bin": { "layerfs": "src/layerfs.js" @@ -17,7 +17,7 @@ "node": ">=20" } }, - "../sdk": { + "../agent": { "name": "@layerfs/agent", "version": "1.1.0", "engines": { @@ -25,7 +25,7 @@ } }, "node_modules/@layerfs/agent": { - "resolved": "../sdk", + "resolved": "../agent", "link": true } } diff --git a/api/agent/cli/package.json b/api/cli/package.json similarity index 91% rename from api/agent/cli/package.json rename to api/cli/package.json index 2cc5be8a5..494635e2e 100644 --- a/api/agent/cli/package.json +++ b/api/cli/package.json @@ -13,7 +13,7 @@ "./package.json": "./package.json" }, "dependencies": { - "@layerfs/agent": "file:../sdk" + "@layerfs/agent": "file:../agent" }, "engines": { "node": ">=20" diff --git a/api/agent/cli/src/argv.js b/api/cli/src/argv.js similarity index 100% rename from api/agent/cli/src/argv.js rename to api/cli/src/argv.js diff --git a/api/agent/cli/src/branch/diff_branches.js b/api/cli/src/branch/diff_branches.js similarity index 100% rename from api/agent/cli/src/branch/diff_branches.js rename to api/cli/src/branch/diff_branches.js diff --git a/api/agent/cli/src/branch/diff_commits.js b/api/cli/src/branch/diff_commits.js similarity index 100% rename from api/agent/cli/src/branch/diff_commits.js rename to api/cli/src/branch/diff_commits.js diff --git a/api/agent/cli/src/branch/fork.js b/api/cli/src/branch/fork.js similarity index 100% rename from api/agent/cli/src/branch/fork.js rename to api/cli/src/branch/fork.js diff --git a/api/agent/cli/src/branch/index.js b/api/cli/src/branch/index.js similarity index 100% rename from api/agent/cli/src/branch/index.js rename to api/cli/src/branch/index.js diff --git a/api/agent/cli/src/branch/list_commits.js b/api/cli/src/branch/list_commits.js similarity index 100% rename from api/agent/cli/src/branch/list_commits.js rename to api/cli/src/branch/list_commits.js diff --git a/api/agent/cli/src/branch/merge.js b/api/cli/src/branch/merge.js similarity index 100% rename from api/agent/cli/src/branch/merge.js rename to api/cli/src/branch/merge.js diff --git a/api/agent/cli/src/branch/publish.js b/api/cli/src/branch/publish.js similarity index 100% rename from api/agent/cli/src/branch/publish.js rename to api/cli/src/branch/publish.js diff --git a/api/agent/cli/src/calls.js b/api/cli/src/calls.js similarity index 89% rename from api/agent/cli/src/calls.js rename to api/cli/src/calls.js index 4f22ebd9e..28e69dabf 100644 --- a/api/agent/cli/src/calls.js +++ b/api/cli/src/calls.js @@ -1,7 +1,7 @@ // The layerfs call table (#428 CLI), assembled from one file per command: -// api/agent/cli/src//.js mirrors api/agent/sdk/src//.js, +// api/cli/src//.js mirrors api/agent/src//.js, // and runs as `layerfs `. Parsing (argv.js), help (help.js) -// and dispatch (main.js) read the table; api/how-to-use/agent.md is its reference. +// and dispatch (main.js) read the table; api/docs/agent.md is its reference. // LayerFS.open and close happen inside every command, so they have none. // // Each command file exports { args, options, summary, run, prepare? }. diff --git a/api/agent/cli/src/common.js b/api/cli/src/common.js similarity index 100% rename from api/agent/cli/src/common.js rename to api/cli/src/common.js diff --git a/api/agent/cli/src/fs/apply.js b/api/cli/src/fs/apply.js similarity index 100% rename from api/agent/cli/src/fs/apply.js rename to api/cli/src/fs/apply.js diff --git a/api/agent/cli/src/fs/blame.js b/api/cli/src/fs/blame.js similarity index 100% rename from api/agent/cli/src/fs/blame.js rename to api/cli/src/fs/blame.js diff --git a/api/agent/cli/src/fs/cp.js b/api/cli/src/fs/cp.js similarity index 100% rename from api/agent/cli/src/fs/cp.js rename to api/cli/src/fs/cp.js diff --git a/api/agent/cli/src/fs/diff_files.js b/api/cli/src/fs/diff_files.js similarity index 100% rename from api/agent/cli/src/fs/diff_files.js rename to api/cli/src/fs/diff_files.js diff --git a/api/agent/cli/src/fs/edit.js b/api/cli/src/fs/edit.js similarity index 100% rename from api/agent/cli/src/fs/edit.js rename to api/cli/src/fs/edit.js diff --git a/api/agent/cli/src/fs/glob.js b/api/cli/src/fs/glob.js similarity index 100% rename from api/agent/cli/src/fs/glob.js rename to api/cli/src/fs/glob.js diff --git a/api/agent/cli/src/fs/grep.js b/api/cli/src/fs/grep.js similarity index 100% rename from api/agent/cli/src/fs/grep.js rename to api/cli/src/fs/grep.js diff --git a/api/agent/cli/src/fs/index.js b/api/cli/src/fs/index.js similarity index 100% rename from api/agent/cli/src/fs/index.js rename to api/cli/src/fs/index.js diff --git a/api/agent/cli/src/fs/list.js b/api/cli/src/fs/list.js similarity index 100% rename from api/agent/cli/src/fs/list.js rename to api/cli/src/fs/list.js diff --git a/api/agent/cli/src/fs/mkdir.js b/api/cli/src/fs/mkdir.js similarity index 100% rename from api/agent/cli/src/fs/mkdir.js rename to api/cli/src/fs/mkdir.js diff --git a/api/agent/cli/src/fs/mv.js b/api/cli/src/fs/mv.js similarity index 100% rename from api/agent/cli/src/fs/mv.js rename to api/cli/src/fs/mv.js diff --git a/api/agent/cli/src/fs/read.js b/api/cli/src/fs/read.js similarity index 100% rename from api/agent/cli/src/fs/read.js rename to api/cli/src/fs/read.js diff --git a/api/agent/cli/src/fs/rm.js b/api/cli/src/fs/rm.js similarity index 100% rename from api/agent/cli/src/fs/rm.js rename to api/cli/src/fs/rm.js diff --git a/api/agent/cli/src/fs/stat.js b/api/cli/src/fs/stat.js similarity index 100% rename from api/agent/cli/src/fs/stat.js rename to api/cli/src/fs/stat.js diff --git a/api/agent/cli/src/fs/write.js b/api/cli/src/fs/write.js similarity index 100% rename from api/agent/cli/src/fs/write.js rename to api/cli/src/fs/write.js diff --git a/api/agent/cli/src/help.js b/api/cli/src/help.js similarity index 100% rename from api/agent/cli/src/help.js rename to api/cli/src/help.js diff --git a/api/agent/cli/src/layerfs.js b/api/cli/src/layerfs.js similarity index 100% rename from api/agent/cli/src/layerfs.js rename to api/cli/src/layerfs.js diff --git a/api/agent/cli/src/main.js b/api/cli/src/main.js similarity index 100% rename from api/agent/cli/src/main.js rename to api/cli/src/main.js diff --git a/api/agent/cli/src/output.js b/api/cli/src/output.js similarity index 100% rename from api/agent/cli/src/output.js rename to api/cli/src/output.js diff --git a/api/agent/cli/src/project/index.js b/api/cli/src/project/index.js similarity index 100% rename from api/agent/cli/src/project/index.js rename to api/cli/src/project/index.js diff --git a/api/agent/cli/src/project/init.js b/api/cli/src/project/init.js similarity index 100% rename from api/agent/cli/src/project/init.js rename to api/cli/src/project/init.js diff --git a/api/agent/cli/src/project/list_branches.js b/api/cli/src/project/list_branches.js similarity index 100% rename from api/agent/cli/src/project/list_branches.js rename to api/cli/src/project/list_branches.js diff --git a/api/agent/cli/src/project/list_sandboxes.js b/api/cli/src/project/list_sandboxes.js similarity index 100% rename from api/agent/cli/src/project/list_sandboxes.js rename to api/cli/src/project/list_sandboxes.js diff --git a/api/agent/cli/src/sandbox/close.js b/api/cli/src/sandbox/close.js similarity index 100% rename from api/agent/cli/src/sandbox/close.js rename to api/cli/src/sandbox/close.js diff --git a/api/agent/cli/src/sandbox/create.js b/api/cli/src/sandbox/create.js similarity index 100% rename from api/agent/cli/src/sandbox/create.js rename to api/cli/src/sandbox/create.js diff --git a/api/agent/cli/src/sandbox/index.js b/api/cli/src/sandbox/index.js similarity index 100% rename from api/agent/cli/src/sandbox/index.js rename to api/cli/src/sandbox/index.js diff --git a/api/agent/cli/src/sandbox/list_workspaces.js b/api/cli/src/sandbox/list_workspaces.js similarity index 100% rename from api/agent/cli/src/sandbox/list_workspaces.js rename to api/cli/src/sandbox/list_workspaces.js diff --git a/api/agent/cli/src/workspace/commit.js b/api/cli/src/workspace/commit.js similarity index 100% rename from api/agent/cli/src/workspace/commit.js rename to api/cli/src/workspace/commit.js diff --git a/api/agent/cli/src/workspace/exec.js b/api/cli/src/workspace/exec.js similarity index 100% rename from api/agent/cli/src/workspace/exec.js rename to api/cli/src/workspace/exec.js diff --git a/api/agent/cli/src/workspace/index.js b/api/cli/src/workspace/index.js similarity index 100% rename from api/agent/cli/src/workspace/index.js rename to api/cli/src/workspace/index.js diff --git a/api/agent/cli/src/workspace/mount.js b/api/cli/src/workspace/mount.js similarity index 100% rename from api/agent/cli/src/workspace/mount.js rename to api/cli/src/workspace/mount.js diff --git a/api/agent/cli/src/workspace/unmount.js b/api/cli/src/workspace/unmount.js similarity index 100% rename from api/agent/cli/src/workspace/unmount.js rename to api/cli/src/workspace/unmount.js diff --git a/api/agent/cli/test/cli.test.mjs b/api/cli/test/cli.test.mjs similarity index 94% rename from api/agent/cli/test/cli.test.mjs rename to api/cli/test/cli.test.mjs index c9fc685de..3b97c5f12 100644 --- a/api/agent/cli/test/cli.test.mjs +++ b/api/cli/test/cli.test.mjs @@ -1,9 +1,9 @@ -// The layerfs command end to end: each test spawns `node api/agent/cli/src/layerfs.js` +// The layerfs command end to end: each test spawns `node api/cli/src/layerfs.js` // with the real @layerfs/agent JavaScript over a stand-in native binding -// (api/agent/sdk/test/fixture/fake-native.cjs, shared with the SDK +// (api/agent/test/fixture/fake-native.cjs, shared with the SDK // tests), which logs every binding call. No Docker, Store // or daemon; runs anywhere: -// node --test api/agent/cli/test/cli.test.mjs +// node --test api/cli/test/cli.test.mjs import assert from "node:assert/strict"; import { spawnSync } from "node:child_process"; import { existsSync, mkdirSync, mkdtempSync, readdirSync, readFileSync, realpathSync, rmSync, writeFileSync } from "node:fs"; @@ -15,10 +15,10 @@ import { fileURLToPath } from "node:url"; import { CALLS, INIT } from "../src/calls.js"; import { usage } from "../src/help.js"; import { tables, written } from "./doc-tables.mjs"; -import { CASES, ENV, contains, made, plain } from "../../sdk/test/fixture/cases.mjs"; +import { CASES, ENV, contains, made, plain } from "../../agent/test/fixture/cases.mjs"; const CLI = fileURLToPath(new URL("../src/layerfs.js", import.meta.url)); -const FAKE = fileURLToPath(new URL("../../sdk/test/fixture/fake-native.cjs", import.meta.url)); +const FAKE = fileURLToPath(new URL("../../agent/test/fixture/fake-native.cjs", import.meta.url)); const work = realpathSync(mkdtempSync(join(tmpdir(), "layerfs-cli-"))); after(() => rmSync(work, { recursive: true, force: true })); @@ -42,7 +42,7 @@ mkdirSync(source); writeFileSync(join(source, "README.md"), "hi\n"); const WS = "1:/workspaces/w1"; -// Consistency with the SDK: each shared case (api/agent/sdk/test/ +// Consistency with the SDK: each shared case (api/agent/test/ // fixture/cases.mjs, whose expected results the SDK's own calls.mjs checks) // runs through the SDK in this process and through the command, over the // same stand-in binding and settings. The command must make the same binding @@ -239,15 +239,15 @@ test("there are no short forms: a family with no call, or an old lfs name, exits assert.deepEqual(cli(["sandbox", "list-workspaces", "2"]).ops, ["sandbox.list_workspaces"]); }); -test("how-to-use/agent.md holds the tables the call table writes", () => { +test("docs/agent.md holds the tables the call table writes", () => { assert.deepEqual(written(), tables()); }); // The CLI's files mirror the agent SDK's: every SDK call file has a command // file of the same family and name, and nothing else (index.js and the SDK's // fs/body.js helper aside). A new SDK call without its command fails here. -test("api/agent/cli/src//.js mirrors api/agent/sdk/src//.js", () => { - const SDK = fileURLToPath(new URL("../../sdk/src/", import.meta.url)); +test("api/cli/src//.js mirrors api/agent/src//.js", () => { + const SDK = fileURLToPath(new URL("../../agent/src/", import.meta.url)); const SRC = fileURLToPath(new URL("../src/", import.meta.url)); const calls = (root, family, skip) => readdirSync(join(root, family)).filter((f) => f.endsWith(".js") && !skip.includes(f)).sort(); for (const family of ["project", "branch", "fs", "workspace", "sandbox"]) { diff --git a/api/agent/cli/test/doc-tables.mjs b/api/cli/test/doc-tables.mjs similarity index 86% rename from api/agent/cli/test/doc-tables.mjs rename to api/cli/test/doc-tables.mjs index 8fb29b57e..f921dcd89 100644 --- a/api/agent/cli/test/doc-tables.mjs +++ b/api/cli/test/doc-tables.mjs @@ -1,14 +1,14 @@ -// The command table of api/how-to-use/agent.md, written from the call table so the +// The command table of api/docs/agent.md, written from the call table so the // doc cannot drift: every SDK call with its command. // cli.test.mjs checks the doc holds exactly these; after changing the table, // rewrite it with: -// node api/agent/cli/test/doc-tables.mjs --write +// node api/cli/test/doc-tables.mjs --write import { readFileSync, writeFileSync } from "node:fs"; import { fileURLToPath } from "node:url"; import { CALLS, INIT } from "../src/calls.js"; import { usage } from "../src/help.js"; -export const DOC = fileURLToPath(new URL("../../../how-to-use/agent.md", import.meta.url)); +export const DOC = fileURLToPath(new URL("../../docs/agent.md", import.meta.url)); const row = (cells) => `| ${cells.join(" | ")} |`; diff --git a/api/agent/cli/test/verify/cli_real.mjs b/api/cli/test/verify/cli_real.mjs similarity index 95% rename from api/agent/cli/test/verify/cli_real.mjs rename to api/cli/test/verify/cli_real.mjs index 5dabf64a6..8cd956b96 100644 --- a/api/agent/cli/test/verify/cli_real.mjs +++ b/api/cli/test/verify/cli_real.mjs @@ -1,6 +1,6 @@ // The layerfs command against the real SDK, Store, Docker and daemon (#428), // checked for consistency with the SDK. One part of the shared scenario -// (api/agent/sdk/test/verify/scenario.mjs, every agent call) runs +// (api/agent/test/verify/scenario.mjs, every agent call) runs // twice, each time on its own fresh project and Store: // - first through the SDK in this process, each step checked for // correctness; @@ -14,14 +14,14 @@ // and a Commit's stored bytes (PER_RUN). // Disposable Store only. Under the E2E launcher (its Store volume, // deployment and sealed Linux bundle for this commit): -// python3 tools/worktree.py run --resources --bundle --timeout 100 -- node api/agent/cli/test/verify/cli_real.mjs inner +// python3 tools/worktree.py run --resources --bundle --timeout 100 -- node api/cli/test/verify/cli_real.mjs inner import assert from "node:assert/strict"; import { spawnSync } from "node:child_process"; import { mkdirSync, mkdtempSync, rmSync } from "node:fs"; import { tmpdir } from "node:os"; import { dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; -import { PARTS, source, throughSdk, verify } from "../../../sdk/test/verify/scenario.mjs"; +import { PARTS, source, throughSdk, verify } from "../../../agent/test/verify/scenario.mjs"; const [mode, part] = process.argv.slice(2); if (mode !== "inner" || !PARTS[part]) throw new Error("usage: cli_real.mjs inner (under tools/worktree.py run)"); diff --git a/api/how-to-use/agent.md b/api/docs/agent.md similarity index 97% rename from api/how-to-use/agent.md rename to api/docs/agent.md index e7d63363c..53f055d86 100644 --- a/api/how-to-use/agent.md +++ b/api/docs/agent.md @@ -115,7 +115,7 @@ record of which names it initialized. Init refuses a name whose entry exists (`Exists`). Once that entry is deleted, after the project's Sandboxes are removed, any process, including the one that made it, can initialize the name again. The SDK has no remove method; a host that removes a project deletes the entry -and the project's volume itself. `node api/agent/sdk/test/reinit.mjs` checks this with +and the project's volume itself. `node api/agent/test/reinit.mjs` checks this with the real binding: Init, `Exists`, delete the entry, Init again in one process. ### Calls in parallel @@ -140,7 +140,7 @@ Keep each agent's operations on a Workspace sequential. | `LAYERFS_IMAGE` | Exact immutable runtime `sha256:...` digest a new Sandbox runs. A running Sandbox keeps the image it started with. | | `LAYERFS_VOLUME` | Existing named local VM volume shared by the project's daemons. | | `LAYERFS_DAEMON` | Host path to the built Linux daemon executable. | -| `LAYERFS_NATIVE` | Optional path of the real addon; defaults to `api/binding/layerfs.node`. | +| `LAYERFS_NATIVE` | Optional path of the real addon; defaults to `engine/crates/layerfs-node/layerfs.node`. | | `LAYERFS_WORKER_ENDPOINT` | macOS and Windows: the endpoint file of the LayerFS home's worker, which then makes every binding call. Any integration may set it. | | `LAYERFS_STORE_PATH` | The installed Store file this client's Store calls open in this process. It is `global/store.sqlite` in the project's volume, `/layerfs-store/global/store.sqlite` where that volume is mounted at `/layerfs-store`. Linux only, on a local filesystem the daemons share; elsewhere Store calls fail `Unsupported`. Unset, they fail `InvalidInput`. | | `LAYERFS_CONTAINER_PREFIX` | Optional. Names every container this client creates `-` (default prefix `layerfs-`); another LayerFS home on the same Docker engine sets its own, so names never collide. Docker's name rule applies (an ASCII letter or digit, then letters, digits, `_`, `.`, `-`, at most 128). A name another container holds refuses the create before any effect. | @@ -319,7 +319,7 @@ detached `ArrayBuffer` are refused as InvalidInput, and so is anything else, such as an array of numbers. The bytes are copied once the call starts, after the client's Store is open, so do not change them until the call settles. Reads are text only: `fs.read` refuses a file that is not UTF-8 text as -`Binary`, and `fs.stat` reports its size. `node api/agent/sdk/test/binary_write.mjs` +`Binary`, and `fs.stat` reports its size. `node api/agent/test/binary_write.mjs` checks these forms and refusals on Linux. ### Pages and reads @@ -384,18 +384,18 @@ the LayerFS home's worker on macOS and Windows, and fail `Unsupported` anywhere ### Install and run -The command is the `api/agent/cli/` folder of a LayerFS checkout; it isn't published to +The command is the `api/cli/` folder of a LayerFS checkout; it isn't published to npm. It needs Node 20 or newer and the SDK's native addon (`npm run build:native` in `api`, or `LAYERFS_NATIVE`). ```bash npm --prefix "$LAYERFS_REPO/api" install -npm --prefix "$LAYERFS_REPO/api/agent/cli" install -"$LAYERFS_REPO/api/agent/cli/src/layerfs.js" help +npm --prefix "$LAYERFS_REPO/api/cli" install +"$LAYERFS_REPO/api/cli/src/layerfs.js" help ``` The package's bin is `layerfs`; link it onto `PATH` (for example `npm link` in -`api/agent/cli/`) to type `layerfs` alone. A short session: +`api/cli/`) to type `layerfs` alone. A short session: ```bash export LAYERFS_PROJECT=shop # or --project shop on each command @@ -455,12 +455,12 @@ layerfs sandbox close 1 ### Every call -Each command is one file, `api/agent/cli/src//.js`, beside the SDK's own -`api/agent/sdk/src//.js` (`layerfs init` is -`api/agent/cli/src/project/init.js`, where the SDK keeps Init). Each family's `index.js` -lists its commands in help order, and `api/agent/cli/src/calls.js` assembles them into +Each command is one file, `api/cli/src//.js`, beside the SDK's own +`api/agent/src//.js` (`layerfs init` is +`api/cli/src/project/init.js`, where the SDK keeps Init). Each family's `index.js` +lists its commands in help order, and `api/cli/src/calls.js` assembles them into the call table. The table below is written from it by -`node api/agent/cli/test/doc-tables.mjs --write`; `api/agent/cli/test/cli.test.mjs` fails when the +`node api/cli/test/doc-tables.mjs --write`; `api/cli/test/cli.test.mjs` fails when the table differs, and when a family's files stop matching the SDK's. diff --git a/api/how-to-use/backend.md b/api/docs/backend.md similarity index 98% rename from api/how-to-use/backend.md rename to api/docs/backend.md index 73613a3ff..cf61b9e29 100644 --- a/api/how-to-use/backend.md +++ b/api/docs/backend.md @@ -146,9 +146,9 @@ Concurrent calls append whole lines; order follows completion, so join by `id`. The trace is diagnostic timing, not a benchmark measurement. Off means no scope, no observed exchange, no daemon timing and byte-identical replies. -Checks: `node api/agent/sdk/test/trace.mjs ` runs one case (`on`, `off`, +Checks: `node api/agent/test/trace.mjs ` runs one case (`on`, `off`, `failure`, `layerfs-env`, `start`, `ids`, `no-content`) over a stand-in binding; `layerfs-env` checks that an integration's own prefixed names are not -settings. `node api/agent/sdk/test/verify/trace_real.mjs inner` traces a fork, +settings. `node api/agent/test/verify/trace_real.mjs inner` traces a fork, mount, exec, process, commit and merge on a fresh Disposable Store with the `LAYERFS_TRACE` names set. diff --git a/api/how-to-use/runtime.md b/api/docs/runtime.md similarity index 100% rename from api/how-to-use/runtime.md rename to api/docs/runtime.md diff --git a/api/layerfs-api/Cargo.toml b/api/layerfs-api/Cargo.toml deleted file mode 100644 index 2fecc1ff5..000000000 --- a/api/layerfs-api/Cargo.toml +++ /dev/null @@ -1,29 +0,0 @@ -[package] -name = "layerfs-api" -description = "The SDK's public surface behind the JavaScript SDK, one function per method: project Init and Branches, fs and branch Store methods over layerfs-store-service, and Sandbox control" -version.workspace = true -edition.workspace = true -rust-version.workspace = true -license.workspace = true - -[dependencies] -layerfs-bridge = { path = "../../engine/crates/layerfs-bridge" } -layerfs-content = { path = "../../core/crates/layerfs-content" } -layerfs-history = { path = "../../core/crates/layerfs-history" } -layerfs-persistence = { path = "../../engine/crates/layerfs-persistence" } -layerfs-storage = { path = "../../core/crates/layerfs-storage" } -layerfs-telemetry = { path = "../../core/crates/layerfs-telemetry" } -layerfs-project = { path = "../../engine/crates/layerfs-project" } -layerfs-sandbox = { path = "../../engine/crates/layerfs-sandbox" } -layerfs-store-service = { path = "../../engine/crates/layerfs-store-service" } - -[dev-dependencies] -nix = { version = "=0.31.3", features = ["fs", "user", "process"] } -layerfs-daemon = { path = "../../engine/crates/layerfs-daemon" } -layerfs-fuse = { path = "../../engine/crates/layerfs-fuse" } -# #364: the write-cost harness times BLAKE3 over the bytes it writes. -blake3 = { version = "=1.8.5", default-features = false } -# The Store method tests bind private Workspaces and count the Store's rows. -layerfs-overlay = { path = "../../engine/crates/layerfs-overlay" } -layerfs-workspace = { path = "../../engine/crates/layerfs-workspace" } -rusqlite = { version = "=0.40.2", features = ["cache", "limits", "blob"] } diff --git a/api/package.json b/api/package.json index 33adaee95..b71407e7b 100644 --- a/api/package.json +++ b/api/package.json @@ -1,11 +1,11 @@ { "name": "layerfs-js", "version": "1.1.0", - "description": "The LayerFS JavaScript packages (#428): @layerfs/agent, @layerfs/backend and @layerfs/runtime, beside the native addon crate. `npm install` here links them; it downloads nothing.", + "description": "The LayerFS JavaScript packages (#428): @layerfs/agent, @layerfs/backend and @layerfs/runtime, which load the engine's native addon (engine/crates/layerfs-node). `npm install` here links them; it downloads nothing.", "private": true, "type": "module", "workspaces": [ - "agent/sdk", + "agent", "backend", "runtime" ], diff --git a/api/runtime/src/platform/windows/index.js b/api/runtime/src/platform/windows/index.js index 01a469bb3..6351f9ed2 100644 --- a/api/runtime/src/platform/windows/index.js +++ b/api/runtime/src/platform/windows/index.js @@ -74,8 +74,8 @@ async function launch(settings, held) { try { if (!answer.sdk || !Object.keys(answer.sdk).length) throw refuse("Failed", "the WSL worker supplied no SDK identity"); for (const [path, expected] of Object.entries(answer.sdk)) { - if (!path.startsWith("api/agent/sdk/") || path.includes("..")) throw refuse("Failed", "invalid SDK identity path"); - const source = readFileSync(join(agent, path.slice("api/agent/sdk/".length)), "utf8").replaceAll("\r\n", "\n"); + if (!path.startsWith("api/agent/") || path.includes("..")) throw refuse("Failed", "invalid SDK identity path"); + const source = readFileSync(join(agent, path.slice("api/agent/".length)), "utf8").replaceAll("\r\n", "\n"); if (createHash("sha256").update(source).digest("hex") !== expected) throw refuse("Failed", `this @layerfs/agent differs from the sealed Linux build: ${path}`); } } catch (error) { child.stdin.end(); throw error; } diff --git a/api/runtime/src/worker/server.js b/api/runtime/src/worker/server.js index 6a40c5651..036d86903 100644 --- a/api/runtime/src/worker/server.js +++ b/api/runtime/src/worker/server.js @@ -195,7 +195,7 @@ server.listen(config.port, config.host, () => { console.error(`layerfs worker: listening on ${config.host}:${port}, build ${manifest.build_id}`); if (!stdin) return; // the caller checks its own @layerfs/agent against the sealed one - const sdk = Object.fromEntries(Object.entries(manifest.files).filter(([path]) => path.startsWith("api/agent/sdk/src/"))); + const sdk = Object.fromEntries(Object.entries(manifest.files).filter(([path]) => path.startsWith("api/agent/src/"))); process.stdout.write(frame({ port, build: manifest.build_id, sdk })); process.stdin.on("end", () => shutdown().catch((error) => console.error(error))); process.stdin.resume(); diff --git a/api/runtime/test/runtime.mjs b/api/runtime/test/runtime.mjs index 9dce1fc10..d8108ca1c 100644 --- a/api/runtime/test/runtime.mjs +++ b/api/runtime/test/runtime.mjs @@ -7,7 +7,7 @@ import { tmpdir } from "node:os"; import { join } from "node:path"; import { fileURLToPath } from "node:url"; -const FAKE = fileURLToPath(new URL("../../agent/sdk/test/fixture/fake-native.cjs", import.meta.url)); +const FAKE = fileURLToPath(new URL("../../agent/test/fixture/fake-native.cjs", import.meta.url)); process.env.LAYERFS_NATIVE = FAKE; for (const name of ["TRACE", "TRACE_STEP", "TRACE_START", "WORKER_ENDPOINT", "HOME", "STORE_PATH", "IMAGE", "DAEMON", "VOLUME"]) { delete process.env[`LAYERFS_${name}`]; @@ -273,7 +273,7 @@ try { // an agent client made before the runtime opens keeps its in-process // binding; the runtime's clients, and any made after it, use the worker const { LayerFS } = await import("@layerfs/agent"); - const { fakeWorker } = await import("../../agent/sdk/test/fixture/fake-worker.mjs"); + const { fakeWorker } = await import("../../agent/test/fixture/fake-worker.mjs"); const worker = await fakeWorker((request) => ({ value: request.op === "backend.store.project.get_history" ? { kind: "ok", version: "h1", branches: [], commits: [], more: {}, layers: [] } : { items: [], hasMore: false } })); try { process.env.LAYERFS_STORE_PATH = "/fake/store.sqlite"; @@ -305,7 +305,7 @@ try { } } else if (selected === "macos-worker") { // the macOS worker's start with a stubbed docker CLI and a stand-in worker - const { fakeWorker } = await import("../../agent/sdk/test/fixture/fake-worker.mjs"); + const { fakeWorker } = await import("../../agent/test/fixture/fake-worker.mjs"); const macos = (await import("../src/platform/macos/index.js")).default; const worker = await fakeWorker(undefined, { anySecret: true }); const bundle = join(work, "bundle"); diff --git a/api/scripts/build-native.mjs b/api/scripts/build-native.mjs index c69334bb4..3e591f31a 100644 --- a/api/scripts/build-native.mjs +++ b/api/scripts/build-native.mjs @@ -25,7 +25,7 @@ if (result.status !== 0) process.exit(result.status ?? 1); const artifact = join(target, profile, `liblayerfs_node.${suffix}`); const output = process.env.LAYERFS_NATIVE_OUTPUT ? resolve(root, process.env.LAYERFS_NATIVE_OUTPUT) - : fileURLToPath(new URL("../binding/layerfs.node", import.meta.url)); + : fileURLToPath(new URL("../../engine/crates/layerfs-node/layerfs.node", import.meta.url)); mkdirSync(dirname(output), { recursive: true }); const staged = `${output}.${process.pid}.new`; copyFileSync(artifact, staged); diff --git a/api/scripts/recover-records.mjs b/api/scripts/recover-records.mjs index f88c83343..74d3ae3f7 100644 --- a/api/scripts/recover-records.mjs +++ b/api/scripts/recover-records.mjs @@ -5,7 +5,7 @@ // is untouched in its Docker volume, and the record can be rebuilt from it: // the catalog binding, LayerStack, Init's `main` Branch and the first Layer's // root are rows of the Store; the cursor key only signs page cursors and is new. -// api/binding/examples/restore_record.rs writes the record (#347). +// engine/crates/layerfs-node/examples/restore_record.rs writes the record (#347). // // node api/scripts/recover-records.mjs --home --image // --restore [--apply] [project …] diff --git a/core/crates/layerfs-content/tests/fixture_seal.rs b/core/crates/layerfs-content/tests/fixture_seal.rs index bdabcca51..16099d2dc 100644 --- a/core/crates/layerfs-content/tests/fixture_seal.rs +++ b/core/crates/layerfs-content/tests/fixture_seal.rs @@ -245,8 +245,7 @@ fn no_product_source_can_reseal_during_an_ordinary_test_run() { root.join("Cargo.toml").is_file() && root.join("core/crates").is_dir(), "the scan root is not the workspace" ); - let roots = ["core", "engine", "api/layerfs-api", "api/binding", "tools"] - .map(|relative| root.join(relative)); + let roots = ["core", "engine", "tools"].map(|relative| root.join(relative)); let sources: Vec<_> = roots.iter().flat_map(|path| rust_sources(path)).collect(); let guard = manifest.join("tests/fixture_seal.rs"); assert!( diff --git a/core/docs/architecture/06-limits.md b/core/docs/architecture/06-limits.md index d5530fe7c..01857d247 100644 --- a/core/docs/architecture/06-limits.md +++ b/core/docs/architecture/06-limits.md @@ -553,7 +553,7 @@ not declared product contracts. | directory moved under a parent | at most 256 levels deep | `kernel_mutation::ANCESTRY_STEPS` | | LWW rule include files | 16; later includes are ignored | `lww::MAXIMUM_RULE_FILES` | | writer wait | none since F-040: queued writers wait their turn with no time limit ([record 038](../issues/352/fixes/038-f040-untimed-writer-admission.md); audit A8 and A11 removed) | admission queue, Linux directory lock | -| SDK `project.init` | the caller's required `timeoutMs`; `@layerfs/agent` sends 300 s unless given one (`INIT_TIMEOUT_MS`); no unlimited option (#431; the fixed 60 s `INIT_DEADLINE` is deleted) | `api/binding/src/project.rs` `deadline`, `api/agent/sdk/src/project/init.js` | +| SDK `project.init` | the caller's required `timeoutMs`; `@layerfs/agent` sends 300 s unless given one (`INIT_TIMEOUT_MS`); no unlimited option (#431; the fixed 60 s `INIT_DEADLINE` is deleted) | `engine/crates/layerfs-node/src/project.rs` `deadline`, `api/agent/src/project/init.js` | | mounts per SDK Sandbox / control connections | 16 / 8 (fixed by the SDK) | `sandbox.rs` `DaemonLimits` | ### Service/Bridge — final file save (#252) diff --git a/core/docs/architecture/60-shared-store-foundation.md b/core/docs/architecture/60-shared-store-foundation.md index 68745a28c..809492372 100644 --- a/core/docs/architecture/60-shared-store-foundation.md +++ b/core/docs/architecture/60-shared-store-foundation.md @@ -12,7 +12,7 @@ logical history, unique canonical locator lengths, complete pack lengths and metadata-domain bodies, maintained inside original insert/publication transactions. Read statistics add occupied SQL-page overhead without an object scan. `file` is logical SQLite pages including pages in WAL, not extra WAL allocation. Definitions -and the passed retention screen are in [the backend guide](../../../api/how-to-use/backend.md#storage-figures) +and the passed retention screen are in [the backend guide](../../../api/docs/backend.md#storage-figures) and [counter receipt](../issues/327/COUNTER-SCREEN-20261015.md). The macOS 3.51.0 component verifier observed CannotOpen on native read-only open diff --git a/core/docs/architecture/61-direct-store-adapter.md b/core/docs/architecture/61-direct-store-adapter.md index 456d8bc4c..8a1d8ac61 100644 --- a/core/docs/architecture/61-direct-store-adapter.md +++ b/core/docs/architecture/61-direct-store-adapter.md @@ -33,7 +33,7 @@ rows that never change once visible and never an absence. The Store's control reader (session 0), which serves every SDK call, keeps none of its own. The daemon's CanonicalCache budget is the `cache_bytes` the SDK passes at -Sandbox create (`api/binding/src/sandbox.rs`): **64 MiB**, by owner decision +Sandbox create (`engine/crates/layerfs-node/src/sandbox.rs`): **64 MiB**, by owner decision 2026-10-19 (#359, [fix record 031](../issues/352/fixes/031-359-warm-daemon-cache.md)); it was 8 MiB, which one `find`, vitest or `ls -l` of 10,000 entries overran, so a later Workspace on the same daemon read it all again. The RCA LOOKUP facts diff --git a/core/docs/architecture/76-native-mount-session.md b/core/docs/architecture/76-native-mount-session.md index 83c22c515..b5cadc9c0 100644 --- a/core/docs/architecture/76-native-mount-session.md +++ b/core/docs/architecture/76-native-mount-session.md @@ -286,7 +286,7 @@ create and on reopen, so a Sandbox created by an earlier build is refused and must be closed and created again. A backend other than this Docker one has to give the same contract, with its own init (Podman's catatonit, a VM's init) or an equivalent. The real-Docker check is -[`reap_real.mjs`](../../../api/agent/sdk/test/verify/reap_real.mjs): orphans that exit +[`reap_real.mjs`](../../../api/agent/test/verify/reap_real.mjs): orphans that exit are gone, PID 1 is not the daemon, and `exit 7` still answers 7. The record is [fix 039](../issues/352/fixes/039-f054-sandbox-init-reaper.md). diff --git a/core/docs/architecture/82-sdk-call-channel.md b/core/docs/architecture/82-sdk-call-channel.md index f8160b7db..e9bf25bf2 100644 --- a/core/docs/architecture/82-sdk-call-channel.md +++ b/core/docs/architecture/82-sdk-call-channel.md @@ -6,7 +6,7 @@ The JavaScript SDK has 27 positional methods in four groups (29 before #373 replaced the `sandbox` group with `workspace`; see the #373 update below). The -[SDK guide](../../../api/how-to-use/agent.md) lists signatures, environment configuration, +[SDK guide](../../../api/docs/agent.md) lists signatures, environment configuration, read/page limits and compatibility. [SPEC](../issues/327/SPEC.md) describes the UI/server integration; [VERIFICATION](../issues/327/VERIFICATION.md) owns acceptance. No harness, agent/call metadata, remove alias or public inspect is retained. @@ -255,7 +255,7 @@ a process id names its Sandbox. The native ops are `workspace.*`, control records and its timing names (`sandbox.mount.bind`, `sandbox.mount.attach`) are unchanged. Design and owner decisions: [#373](../issues/373/README.md); placement and idle close are described in the -[SDK guide](../../../api/how-to-use/agent.md#sandboxes-and-workspaces). +[SDK guide](../../../api/docs/agent.md#sandboxes-and-workspaces). ## Issue #428 source update (2026-10-23): backend names and packages @@ -271,7 +271,7 @@ over the reclaim `operator.sandbox.list` did; `project.list_sandboxes` now only lists. `@layerfs/agent` exports `RENAMED_METHODS` for reading older traces. The Rust module paths (`operator/`) keep their names. -The JavaScript is split into `api/agent/sdk` (`LayerFS`), +The JavaScript is split into `api/agent` (`LayerFS`), `api/backend` (`LayerFSBackend.of(shop)`, one file per method) and `api/runtime` (`LayerFSRuntime.open`, on a LayerFS home). `@layerfs/sdk/operator` and its `inspect.snapshot` are gone; the snapshot is @@ -285,7 +285,7 @@ New calls: `sandbox.create`, `sandbox.close` and mounting into a chosen Sandbox (agent), and `backend.daemon.sandbox.get_log`, which reads a Sandbox's daemon log once through the Engine where the binding runs. See the -[backend guide](../../../api/how-to-use/backend.md#a-sandboxs-log). +[backend guide](../../../api/docs/backend.md#a-sandboxs-log). ## Project Store composition (#463) @@ -298,9 +298,9 @@ seal. It requires Disposable explicitly and preserves original failure custody. Project depends on Bridge for the existing provisioning records and channel install protocol; it defines no second format or protocol. -[`layerfs-api::project`](../../../api/layerfs-api/src/project/mod.rs) and its +[`layerfs-api::project`](../../../engine/crates/layerfs-api/src/project/mod.rs) and its root retain the existing public names as re-exports. Its Control owner calls Project's `install_file` without changing correlation or quarantine. The -[Node binding](../../../api/binding/src/project.rs) calls Project's Init once +[Node binding](../../../engine/crates/layerfs-node/src/project.rs) calls Project's Init once directly. This is ownership relocation only; no canonical identity, Store format, behavior or performance claim changes. diff --git a/docs/README.md b/docs/README.md index b67d78b45..793b96abd 100644 --- a/docs/README.md +++ b/docs/README.md @@ -5,7 +5,7 @@ ## LayerFS 1.1.0 (release candidate) - [Release record, compatibility and the owner waiver](release-notes/1.1.0/README.md) -- [JavaScript packages wiki](../api/README.md) and its [how-to guides](../api/how-to-use/) +- [JavaScript packages wiki](../api/README.md) and its [how-to guides](../api/docs/) ## Use LayerFS v0.1.7 diff --git a/docs/general/parallel-worktrees.md b/docs/general/parallel-worktrees.md index 575d532b5..8f742c2f0 100644 --- a/docs/general/parallel-worktrees.md +++ b/docs/general/parallel-worktrees.md @@ -43,7 +43,7 @@ registered checkout without copying scripts into it or merging branches first. | Linux Cargo target | Labelled private Docker volume at `/work/target` | | Linux Cargo home | Separate labelled private Docker volume at `/cargo-home` | | Toolchain/images | Pinned toolchain and shared immutable installed images | -| E2E artifacts | Unique sealed bundle containing daemon, addon, SDK runtime/operator/test files, the `layerfs` command (`api/agent/cli/src`, `api/agent/cli/test`), hashes and source identity | +| E2E artifacts | Unique sealed bundle containing daemon, addon, SDK runtime/operator/test files, the `layerfs` command (`api/cli/src`, `api/cli/test`), hashes and source identity | | E2E writable state | Unique per-run Store volume and SDK home, container prefix, trace, and output receipt | ## Prepare dependencies and optional target seeds @@ -131,7 +131,7 @@ refuses workspace aggregates, target/config overrides and `fs-bench-pro`. ## Run pinned Linux E2E artifacts ```sh -python3 tools/worktree.py run --resources /absolute/path/resources.json --bundle /absolute/path/to/sealed-linux-bundle --timeout 90 -- node api/agent/sdk/test/verify/direct_locking_real.mjs inner +python3 tools/worktree.py run --resources /absolute/path/resources.json --bundle /absolute/path/to/sealed-linux-bundle --timeout 90 -- node api/agent/test/verify/direct_locking_real.mjs inner ``` Select the owning test's Linux entrypoint. Tests that bootstrap their own outer diff --git a/docs/general/sdk.md b/docs/general/sdk.md index e492beeed..c299eea7d 100644 --- a/docs/general/sdk.md +++ b/docs/general/sdk.md @@ -6,7 +6,7 @@ > gate. Owner direction of 2026-10-12 governs the implementation and measurements. > > Relocation 2026-10-15 ([#327](https://github.com/Ephemeral-AI-Lab/layerfs/issues/327)): -> the crate is renamed `layerfs-sdk` -> `layerfs-api` at `api/layerfs-api` +> the crate is renamed `layerfs-sdk` -> `layerfs-api` at `engine/crates/layerfs-api` > and regrouped as `project/`, `branch/` and `sandbox/`; links below follow the move. > The layout table stays pinned to `ce4e214d9`. See `core/docs/issues/327/SPEC.md`. > @@ -67,12 +67,12 @@ Every permitted new Store explicitly selects Disposable/WAL/synchronous=OFF. Init publishes its original initial Layer and Branch, seals the sole Store, and returns a closed file and the actual original acknowledgements. -[Fork](../../api/layerfs-api/src/branch/fork.rs) preserves the original +[Fork](../../engine/crates/layerfs-api/src/branch/fork.rs) preserves the original explicit ForkRequest and its Layer or Commit source. It does not invent a latest head lookup or a hidden refresh. The history trunk is a LayerStack, not a Branch; the first working Branch is named main today. -[Branches](../../api/layerfs-api/src/project/list_branches.rs) reads one page of a +[Branches](../../engine/crates/layerfs-api/src/project/list_branches.rs) reads one page of a selected stack in name order, with id, name, base Layer and head Commit. It uses one authorized additive Bridge request (tag 14), one reply (tag 17) and one daemon dispatch arm to the existing HistoryCatalog::branches port. The existing control @@ -80,14 +80,14 @@ window is 32 records. The existing authenticated History cursor covers further pages; the caller advances it explicitly. The SDK checks stack identity, result size, ordered names and continuation shape without a second request. -[Commits](../../api/layerfs-api/src/branch/list_commits.rs) renames the public +[Commits](../../engine/crates/layerfs-api/src/branch/list_commits.rs) renames the public history method. It sends the unchanged History request and returns one anchored, bounded ancestry page, newest first. Cursor authentication, captured-head scope, publication semantics and original control bytes are unchanged. ## Sandbox -[Create](../../api/layerfs-api/src/sandbox/create.rs) uses the original +[Create](../../engine/crates/layerfs-api/src/sandbox/create.rs) uses the original explicit deployment/image/volume, private configuration, executable, authentication keys and startup wait. For a fresh Store it creates, uploads, starts, authenticates, sends the original initial Hello, installs the sealed Project once, then waits on @@ -98,7 +98,7 @@ startup and sends no second install. Its manifest must match the supplied Projec only the populated daemon SQLite version may differ from the host Init manifest. A mismatched selection fails at Validate before deployment or control effects. -[Close](../../api/layerfs-api/src/sandbox/close.rs) consumes the owner. It +[Close](../../engine/crates/layerfs-api/src/sandbox/close.rs) consumes the owner. It attempts the original one-second stop once, then deletes once after acknowledged stop, with force=false and v=false. Stop failure does not attempt delete. Either failure retains exact runtime, control, original inputs, handshake, observation @@ -110,14 +110,14 @@ or command/descriptor drain. The caller explicitly unmounts Workspaces first. ## Workspace -[Mount](../../api/layerfs-api/src/sandbox/mount.rs) takes no Project argument; +[Mount](../../engine/crates/layerfs-api/src/sandbox/mount.rs) takes no Project argument; the Sandbox has already selected its Store. It sends the original bind and attach requests once each. The first acknowledgement carries the selected Branch/root; the second carries the mounted directory and native negotiation receipt. A failed attach retains the bound token in MountFailure. No bind, attach, unmount or rollback is guessed from a lost reply or attempted again automatically. -[Exec](../../api/layerfs-api/src/sandbox/exec.rs) delegates ordinary existing +[Exec](../../engine/crates/layerfs-api/src/sandbox/exec.rs) delegates ordinary existing Sandbox execution with the mount as working directory and the deployment's admitted identity. It returns the original runtime owner for Start, streams, exit status and explicit cancellation. It sends no daemon control request, registers no filesystem @@ -125,12 +125,12 @@ Exec, applies no ordinary command deadline, and performs no Commit or unmount. Any other permitted process can use the same mount through ordinary filesystem calls; the filesystem daemon supervises no commands. -[Commit](../../api/layerfs-api/src/sandbox/commit.rs) captures the shared +[Commit](../../engine/crates/layerfs-api/src/sandbox/commit.rs) captures the shared published frontier and returns Committed or UpToDate. It does not filter mutations -by launch route or command completion. [Status](../../api/layerfs-api/src/sandbox/status.rs) +by launch route or command completion. [Status](../../engine/crates/layerfs-api/src/sandbox/status.rs) retains the existing maintained-state scope and never resolves an unknown operation. -[Unmount](../../api/layerfs-api/src/sandbox/unmount.rs) folds normal and +[Unmount](../../engine/crates/layerfs-api/src/sandbox/unmount.rs) folds normal and forced terminal operations into `unmount(token, force)`. Normal success returns None; forced success returns Some(ForcedOutcome) with the original dispositions. Normal Busy keeps the mount usable. Public force does not relinquish unknown @@ -195,7 +195,7 @@ src/ [1444] unmount.rs 33 ``` -SDK tests live under api/layerfs-api/tests; affected daemon tests and +SDK tests live under engine/crates/layerfs-api/tests; affected daemon tests and benchmark runtime tests remain in their owning external test directories. ## Decisions and deferred work diff --git a/engine/AGENTS.md b/engine/AGENTS.md index 8da019f6a..058b9f669 100644 --- a/engine/AGENTS.md +++ b/engine/AGENTS.md @@ -9,7 +9,17 @@ product mental model or campaign-specific benchmark procedures. ## Scope and ownership - Engine owns Bridge, daemon, FUSE, Overlay, Persistence, Project, Sandbox, - Store service and Workspace. Core owns content, history, storage and telemetry. + Store service and Workspace, plus the SDK method surface `layerfs-api` and the + Node binding `layerfs-node`. Core owns content, history, storage and telemetry; + `api/` holds only the published JavaScript packages. +- Project Store Init and install belong to `layerfs-project::store`; `layerfs-api` + retains its public re-exports and the binding makes one direct Project Init + call. SDK-facing daemon integration tests live in `layerfs-api/tests`, with + cheap includes of daemon fixtures. Build the ordinary daemon binary before + running tests that launch it. `LAYERFS_TEST_DAEMON` may select an explicit + binary; otherwise the tests locate the sibling Cargo output. The binding's + [external proof guide](crates/layerfs-node/tests/README.md) describes its + Linux addon tests; the owner keeps `layerfs-node` out of CI. The v0.1.6 reference under root `crates/` and the archived `core/reference-tests` were retired by R9c (2026-10-10) and are absent at HEAD; recover them at @@ -221,7 +231,7 @@ visibility and protection of Store, Overlay and daemon credentials. Ordinary runtime execution owns standard I/O, exit status and caller-requested cancellation. SDK public organization is the eleven operations documented in [the implemented SDK surface](../docs/general/sdk.md), with operation files under -[layerfs-api/src](../api/layerfs-api/src). Project offers init/fork/ +[layerfs-api/src](crates/layerfs-api/src). Project offers init/fork/ branches/commits; Sandbox offers create/close; Workspace offers mount/exec/ commit/status/unmount. Shared control/recovery/diagnostic plumbing lives in base/ and the hidden internal module. Optional WorkspaceApi.exec selects the diff --git a/engine/crates/layerfs-api/Cargo.toml b/engine/crates/layerfs-api/Cargo.toml new file mode 100644 index 000000000..b6020108a --- /dev/null +++ b/engine/crates/layerfs-api/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "layerfs-api" +description = "The SDK's public surface behind the JavaScript SDK, one function per method: project Init and Branches, fs and branch Store methods over layerfs-store-service, and Sandbox control" +version.workspace = true +edition.workspace = true +rust-version.workspace = true +license.workspace = true + +[dependencies] +layerfs-bridge = { path = "../layerfs-bridge" } +layerfs-content = { path = "../../../core/crates/layerfs-content" } +layerfs-history = { path = "../../../core/crates/layerfs-history" } +layerfs-persistence = { path = "../layerfs-persistence" } +layerfs-storage = { path = "../../../core/crates/layerfs-storage" } +layerfs-telemetry = { path = "../../../core/crates/layerfs-telemetry" } +layerfs-project = { path = "../layerfs-project" } +layerfs-sandbox = { path = "../layerfs-sandbox" } +layerfs-store-service = { path = "../layerfs-store-service" } + +[dev-dependencies] +nix = { version = "=0.31.3", features = ["fs", "user", "process"] } +layerfs-daemon = { path = "../layerfs-daemon" } +layerfs-fuse = { path = "../layerfs-fuse" } +# #364: the write-cost harness times BLAKE3 over the bytes it writes. +blake3 = { version = "=1.8.5", default-features = false } +# The Store method tests bind private Workspaces and count the Store's rows. +layerfs-overlay = { path = "../layerfs-overlay" } +layerfs-workspace = { path = "../layerfs-workspace" } +rusqlite = { version = "=0.40.2", features = ["cache", "limits", "blob"] } diff --git a/api/layerfs-api/examples/issue367_rm_probe.rs b/engine/crates/layerfs-api/examples/issue367_rm_probe.rs similarity index 100% rename from api/layerfs-api/examples/issue367_rm_probe.rs rename to engine/crates/layerfs-api/examples/issue367_rm_probe.rs diff --git a/api/layerfs-api/examples/sandbox_kernel_mount.rs b/engine/crates/layerfs-api/examples/sandbox_kernel_mount.rs similarity index 100% rename from api/layerfs-api/examples/sandbox_kernel_mount.rs rename to engine/crates/layerfs-api/examples/sandbox_kernel_mount.rs diff --git a/api/layerfs-api/examples/sandbox_lifecycle.rs b/engine/crates/layerfs-api/examples/sandbox_lifecycle.rs similarity index 100% rename from api/layerfs-api/examples/sandbox_lifecycle.rs rename to engine/crates/layerfs-api/examples/sandbox_lifecycle.rs diff --git a/api/layerfs-api/src/base/args.rs b/engine/crates/layerfs-api/src/base/args.rs similarity index 100% rename from api/layerfs-api/src/base/args.rs rename to engine/crates/layerfs-api/src/base/args.rs diff --git a/api/layerfs-api/src/base/control.rs b/engine/crates/layerfs-api/src/base/control.rs similarity index 100% rename from api/layerfs-api/src/base/control.rs rename to engine/crates/layerfs-api/src/base/control.rs diff --git a/api/layerfs-api/src/base/dispatch.rs b/engine/crates/layerfs-api/src/base/dispatch.rs similarity index 100% rename from api/layerfs-api/src/base/dispatch.rs rename to engine/crates/layerfs-api/src/base/dispatch.rs diff --git a/api/layerfs-api/src/base/failure.rs b/engine/crates/layerfs-api/src/base/failure.rs similarity index 100% rename from api/layerfs-api/src/base/failure.rs rename to engine/crates/layerfs-api/src/base/failure.rs diff --git a/api/layerfs-api/src/base/internal.rs b/engine/crates/layerfs-api/src/base/internal.rs similarity index 100% rename from api/layerfs-api/src/base/internal.rs rename to engine/crates/layerfs-api/src/base/internal.rs diff --git a/api/layerfs-api/src/base/mod.rs b/engine/crates/layerfs-api/src/base/mod.rs similarity index 100% rename from api/layerfs-api/src/base/mod.rs rename to engine/crates/layerfs-api/src/base/mod.rs diff --git a/api/layerfs-api/src/base/recovery.rs b/engine/crates/layerfs-api/src/base/recovery.rs similarity index 100% rename from api/layerfs-api/src/base/recovery.rs rename to engine/crates/layerfs-api/src/base/recovery.rs diff --git a/api/layerfs-api/src/base/sdk.rs b/engine/crates/layerfs-api/src/base/sdk.rs similarity index 100% rename from api/layerfs-api/src/base/sdk.rs rename to engine/crates/layerfs-api/src/base/sdk.rs diff --git a/api/layerfs-api/src/branch/diff_branches.rs b/engine/crates/layerfs-api/src/branch/diff_branches.rs similarity index 100% rename from api/layerfs-api/src/branch/diff_branches.rs rename to engine/crates/layerfs-api/src/branch/diff_branches.rs diff --git a/api/layerfs-api/src/branch/diff_commits.rs b/engine/crates/layerfs-api/src/branch/diff_commits.rs similarity index 100% rename from api/layerfs-api/src/branch/diff_commits.rs rename to engine/crates/layerfs-api/src/branch/diff_commits.rs diff --git a/api/layerfs-api/src/branch/fork.rs b/engine/crates/layerfs-api/src/branch/fork.rs similarity index 100% rename from api/layerfs-api/src/branch/fork.rs rename to engine/crates/layerfs-api/src/branch/fork.rs diff --git a/api/layerfs-api/src/branch/list_commits.rs b/engine/crates/layerfs-api/src/branch/list_commits.rs similarity index 100% rename from api/layerfs-api/src/branch/list_commits.rs rename to engine/crates/layerfs-api/src/branch/list_commits.rs diff --git a/api/layerfs-api/src/branch/merge.rs b/engine/crates/layerfs-api/src/branch/merge.rs similarity index 100% rename from api/layerfs-api/src/branch/merge.rs rename to engine/crates/layerfs-api/src/branch/merge.rs diff --git a/api/layerfs-api/src/branch/mod.rs b/engine/crates/layerfs-api/src/branch/mod.rs similarity index 100% rename from api/layerfs-api/src/branch/mod.rs rename to engine/crates/layerfs-api/src/branch/mod.rs diff --git a/api/layerfs-api/src/branch/publish.rs b/engine/crates/layerfs-api/src/branch/publish.rs similarity index 100% rename from api/layerfs-api/src/branch/publish.rs rename to engine/crates/layerfs-api/src/branch/publish.rs diff --git a/api/layerfs-api/src/fs/apply.rs b/engine/crates/layerfs-api/src/fs/apply.rs similarity index 100% rename from api/layerfs-api/src/fs/apply.rs rename to engine/crates/layerfs-api/src/fs/apply.rs diff --git a/api/layerfs-api/src/fs/blame.rs b/engine/crates/layerfs-api/src/fs/blame.rs similarity index 100% rename from api/layerfs-api/src/fs/blame.rs rename to engine/crates/layerfs-api/src/fs/blame.rs diff --git a/api/layerfs-api/src/fs/cp.rs b/engine/crates/layerfs-api/src/fs/cp.rs similarity index 100% rename from api/layerfs-api/src/fs/cp.rs rename to engine/crates/layerfs-api/src/fs/cp.rs diff --git a/api/layerfs-api/src/fs/diff_files.rs b/engine/crates/layerfs-api/src/fs/diff_files.rs similarity index 100% rename from api/layerfs-api/src/fs/diff_files.rs rename to engine/crates/layerfs-api/src/fs/diff_files.rs diff --git a/api/layerfs-api/src/fs/edit.rs b/engine/crates/layerfs-api/src/fs/edit.rs similarity index 100% rename from api/layerfs-api/src/fs/edit.rs rename to engine/crates/layerfs-api/src/fs/edit.rs diff --git a/api/layerfs-api/src/fs/glob.rs b/engine/crates/layerfs-api/src/fs/glob.rs similarity index 100% rename from api/layerfs-api/src/fs/glob.rs rename to engine/crates/layerfs-api/src/fs/glob.rs diff --git a/api/layerfs-api/src/fs/grep.rs b/engine/crates/layerfs-api/src/fs/grep.rs similarity index 100% rename from api/layerfs-api/src/fs/grep.rs rename to engine/crates/layerfs-api/src/fs/grep.rs diff --git a/api/layerfs-api/src/fs/list.rs b/engine/crates/layerfs-api/src/fs/list.rs similarity index 100% rename from api/layerfs-api/src/fs/list.rs rename to engine/crates/layerfs-api/src/fs/list.rs diff --git a/api/layerfs-api/src/fs/mkdir.rs b/engine/crates/layerfs-api/src/fs/mkdir.rs similarity index 100% rename from api/layerfs-api/src/fs/mkdir.rs rename to engine/crates/layerfs-api/src/fs/mkdir.rs diff --git a/api/layerfs-api/src/fs/mod.rs b/engine/crates/layerfs-api/src/fs/mod.rs similarity index 100% rename from api/layerfs-api/src/fs/mod.rs rename to engine/crates/layerfs-api/src/fs/mod.rs diff --git a/api/layerfs-api/src/fs/mv.rs b/engine/crates/layerfs-api/src/fs/mv.rs similarity index 100% rename from api/layerfs-api/src/fs/mv.rs rename to engine/crates/layerfs-api/src/fs/mv.rs diff --git a/api/layerfs-api/src/fs/read.rs b/engine/crates/layerfs-api/src/fs/read.rs similarity index 100% rename from api/layerfs-api/src/fs/read.rs rename to engine/crates/layerfs-api/src/fs/read.rs diff --git a/api/layerfs-api/src/fs/rm.rs b/engine/crates/layerfs-api/src/fs/rm.rs similarity index 100% rename from api/layerfs-api/src/fs/rm.rs rename to engine/crates/layerfs-api/src/fs/rm.rs diff --git a/api/layerfs-api/src/fs/stat.rs b/engine/crates/layerfs-api/src/fs/stat.rs similarity index 100% rename from api/layerfs-api/src/fs/stat.rs rename to engine/crates/layerfs-api/src/fs/stat.rs diff --git a/api/layerfs-api/src/fs/write.rs b/engine/crates/layerfs-api/src/fs/write.rs similarity index 100% rename from api/layerfs-api/src/fs/write.rs rename to engine/crates/layerfs-api/src/fs/write.rs diff --git a/api/layerfs-api/src/lib.rs b/engine/crates/layerfs-api/src/lib.rs similarity index 100% rename from api/layerfs-api/src/lib.rs rename to engine/crates/layerfs-api/src/lib.rs diff --git a/api/layerfs-api/src/operator/call.rs b/engine/crates/layerfs-api/src/operator/call.rs similarity index 100% rename from api/layerfs-api/src/operator/call.rs rename to engine/crates/layerfs-api/src/operator/call.rs diff --git a/api/layerfs-api/src/operator/inspect/mod.rs b/engine/crates/layerfs-api/src/operator/inspect/mod.rs similarity index 100% rename from api/layerfs-api/src/operator/inspect/mod.rs rename to engine/crates/layerfs-api/src/operator/inspect/mod.rs diff --git a/api/layerfs-api/src/operator/inspect/snapshot.rs b/engine/crates/layerfs-api/src/operator/inspect/snapshot.rs similarity index 100% rename from api/layerfs-api/src/operator/inspect/snapshot.rs rename to engine/crates/layerfs-api/src/operator/inspect/snapshot.rs diff --git a/api/layerfs-api/src/operator/mod.rs b/engine/crates/layerfs-api/src/operator/mod.rs similarity index 100% rename from api/layerfs-api/src/operator/mod.rs rename to engine/crates/layerfs-api/src/operator/mod.rs diff --git a/api/layerfs-api/src/project/list_branches.rs b/engine/crates/layerfs-api/src/project/list_branches.rs similarity index 100% rename from api/layerfs-api/src/project/list_branches.rs rename to engine/crates/layerfs-api/src/project/list_branches.rs diff --git a/api/layerfs-api/src/project/mod.rs b/engine/crates/layerfs-api/src/project/mod.rs similarity index 100% rename from api/layerfs-api/src/project/mod.rs rename to engine/crates/layerfs-api/src/project/mod.rs diff --git a/api/layerfs-api/src/sandbox/close.rs b/engine/crates/layerfs-api/src/sandbox/close.rs similarity index 100% rename from api/layerfs-api/src/sandbox/close.rs rename to engine/crates/layerfs-api/src/sandbox/close.rs diff --git a/api/layerfs-api/src/sandbox/commit.rs b/engine/crates/layerfs-api/src/sandbox/commit.rs similarity index 100% rename from api/layerfs-api/src/sandbox/commit.rs rename to engine/crates/layerfs-api/src/sandbox/commit.rs diff --git a/api/layerfs-api/src/sandbox/create.rs b/engine/crates/layerfs-api/src/sandbox/create.rs similarity index 100% rename from api/layerfs-api/src/sandbox/create.rs rename to engine/crates/layerfs-api/src/sandbox/create.rs diff --git a/api/layerfs-api/src/sandbox/exec.rs b/engine/crates/layerfs-api/src/sandbox/exec.rs similarity index 100% rename from api/layerfs-api/src/sandbox/exec.rs rename to engine/crates/layerfs-api/src/sandbox/exec.rs diff --git a/api/layerfs-api/src/sandbox/mod.rs b/engine/crates/layerfs-api/src/sandbox/mod.rs similarity index 100% rename from api/layerfs-api/src/sandbox/mod.rs rename to engine/crates/layerfs-api/src/sandbox/mod.rs diff --git a/api/layerfs-api/src/sandbox/mount.rs b/engine/crates/layerfs-api/src/sandbox/mount.rs similarity index 100% rename from api/layerfs-api/src/sandbox/mount.rs rename to engine/crates/layerfs-api/src/sandbox/mount.rs diff --git a/api/layerfs-api/src/sandbox/status.rs b/engine/crates/layerfs-api/src/sandbox/status.rs similarity index 100% rename from api/layerfs-api/src/sandbox/status.rs rename to engine/crates/layerfs-api/src/sandbox/status.rs diff --git a/api/layerfs-api/src/sandbox/unmount.rs b/engine/crates/layerfs-api/src/sandbox/unmount.rs similarity index 100% rename from api/layerfs-api/src/sandbox/unmount.rs rename to engine/crates/layerfs-api/src/sandbox/unmount.rs diff --git a/api/layerfs-api/src/sandbox/values.rs b/engine/crates/layerfs-api/src/sandbox/values.rs similarity index 100% rename from api/layerfs-api/src/sandbox/values.rs rename to engine/crates/layerfs-api/src/sandbox/values.rs diff --git a/api/layerfs-api/tests/concurrent_commits.rs b/engine/crates/layerfs-api/tests/concurrent_commits.rs similarity index 100% rename from api/layerfs-api/tests/concurrent_commits.rs rename to engine/crates/layerfs-api/tests/concurrent_commits.rs diff --git a/api/layerfs-api/tests/diff_replay.rs b/engine/crates/layerfs-api/tests/diff_replay.rs similarity index 100% rename from api/layerfs-api/tests/diff_replay.rs rename to engine/crates/layerfs-api/tests/diff_replay.rs diff --git a/api/layerfs-api/tests/diff_resume.rs b/engine/crates/layerfs-api/tests/diff_resume.rs similarity index 100% rename from api/layerfs-api/tests/diff_resume.rs rename to engine/crates/layerfs-api/tests/diff_resume.rs diff --git a/api/layerfs-api/tests/fixtures/merge-forms-root.sqlite b/engine/crates/layerfs-api/tests/fixtures/merge-forms-root.sqlite similarity index 100% rename from api/layerfs-api/tests/fixtures/merge-forms-root.sqlite rename to engine/crates/layerfs-api/tests/fixtures/merge-forms-root.sqlite diff --git a/api/layerfs-api/tests/golden/sdk_methods.txt b/engine/crates/layerfs-api/tests/golden/sdk_methods.txt similarity index 100% rename from api/layerfs-api/tests/golden/sdk_methods.txt rename to engine/crates/layerfs-api/tests/golden/sdk_methods.txt diff --git a/api/layerfs-api/tests/history_ancestry_oracle.rs b/engine/crates/layerfs-api/tests/history_ancestry_oracle.rs similarity index 100% rename from api/layerfs-api/tests/history_ancestry_oracle.rs rename to engine/crates/layerfs-api/tests/history_ancestry_oracle.rs diff --git a/api/layerfs-api/tests/history_diff_oracle.rs b/engine/crates/layerfs-api/tests/history_diff_oracle.rs similarity index 100% rename from api/layerfs-api/tests/history_diff_oracle.rs rename to engine/crates/layerfs-api/tests/history_diff_oracle.rs diff --git a/api/layerfs-api/tests/init.rs b/engine/crates/layerfs-api/tests/init.rs similarity index 100% rename from api/layerfs-api/tests/init.rs rename to engine/crates/layerfs-api/tests/init.rs diff --git a/api/layerfs-api/tests/kernel_application.rs b/engine/crates/layerfs-api/tests/kernel_application.rs similarity index 98% rename from api/layerfs-api/tests/kernel_application.rs rename to engine/crates/layerfs-api/tests/kernel_application.rs index 948f0efb4..0d9b1c595 100644 --- a/api/layerfs-api/tests/kernel_application.rs +++ b/engine/crates/layerfs-api/tests/kernel_application.rs @@ -3,7 +3,7 @@ #[path = "support/daemon_binary.rs"] mod daemon_binary; #[allow(dead_code)] -#[path = "../../../engine/crates/layerfs-daemon/tests/support/host_install.rs"] +#[path = "../../layerfs-daemon/tests/support/host_install.rs"] mod support; use layerfs_api::internal::Control; use layerfs_bridge::{ diff --git a/api/layerfs-api/tests/kernel_mount_routes.rs b/engine/crates/layerfs-api/tests/kernel_mount_routes.rs similarity index 98% rename from api/layerfs-api/tests/kernel_mount_routes.rs rename to engine/crates/layerfs-api/tests/kernel_mount_routes.rs index 3734fab28..cca769069 100644 --- a/api/layerfs-api/tests/kernel_mount_routes.rs +++ b/engine/crates/layerfs-api/tests/kernel_mount_routes.rs @@ -3,10 +3,10 @@ //! frequent fresh mounts and sustained work on one mount. #![cfg(target_os = "linux")] #[allow(dead_code)] -#[path = "../../../engine/crates/layerfs-daemon/tests/support/mounted.rs"] +#[path = "../../layerfs-daemon/tests/support/mounted.rs"] mod mounted; #[allow(dead_code)] -#[path = "../../../engine/crates/layerfs-daemon/tests/support/host_install.rs"] +#[path = "../../layerfs-daemon/tests/support/host_install.rs"] mod support; use layerfs_api::{internal::Control, OperationCause}; use layerfs_bridge::control::{ diff --git a/api/layerfs-api/tests/lane_merge.rs b/engine/crates/layerfs-api/tests/lane_merge.rs similarity index 100% rename from api/layerfs-api/tests/lane_merge.rs rename to engine/crates/layerfs-api/tests/lane_merge.rs diff --git a/api/layerfs-api/tests/local_install.rs b/engine/crates/layerfs-api/tests/local_install.rs similarity index 100% rename from api/layerfs-api/tests/local_install.rs rename to engine/crates/layerfs-api/tests/local_install.rs diff --git a/api/layerfs-api/tests/merge_by_serial.rs b/engine/crates/layerfs-api/tests/merge_by_serial.rs similarity index 100% rename from api/layerfs-api/tests/merge_by_serial.rs rename to engine/crates/layerfs-api/tests/merge_by_serial.rs diff --git a/api/layerfs-api/tests/merge_forms_fixture.rs b/engine/crates/layerfs-api/tests/merge_forms_fixture.rs similarity index 100% rename from api/layerfs-api/tests/merge_forms_fixture.rs rename to engine/crates/layerfs-api/tests/merge_forms_fixture.rs diff --git a/api/layerfs-api/tests/merge_metadata_only.rs b/engine/crates/layerfs-api/tests/merge_metadata_only.rs similarity index 100% rename from api/layerfs-api/tests/merge_metadata_only.rs rename to engine/crates/layerfs-api/tests/merge_metadata_only.rs diff --git a/api/layerfs-api/tests/merge_mixed_forms.rs b/engine/crates/layerfs-api/tests/merge_mixed_forms.rs similarity index 100% rename from api/layerfs-api/tests/merge_mixed_forms.rs rename to engine/crates/layerfs-api/tests/merge_mixed_forms.rs diff --git a/api/layerfs-api/tests/merge_report.rs b/engine/crates/layerfs-api/tests/merge_report.rs similarity index 100% rename from api/layerfs-api/tests/merge_report.rs rename to engine/crates/layerfs-api/tests/merge_report.rs diff --git a/api/layerfs-api/tests/merge_root_oracle.rs b/engine/crates/layerfs-api/tests/merge_root_oracle.rs similarity index 100% rename from api/layerfs-api/tests/merge_root_oracle.rs rename to engine/crates/layerfs-api/tests/merge_root_oracle.rs diff --git a/api/layerfs-api/tests/merge_units.rs b/engine/crates/layerfs-api/tests/merge_units.rs similarity index 100% rename from api/layerfs-api/tests/merge_units.rs rename to engine/crates/layerfs-api/tests/merge_units.rs diff --git a/api/layerfs-api/tests/method_refusal_order.rs b/engine/crates/layerfs-api/tests/method_refusal_order.rs similarity index 100% rename from api/layerfs-api/tests/method_refusal_order.rs rename to engine/crates/layerfs-api/tests/method_refusal_order.rs diff --git a/api/layerfs-api/tests/mount_control.rs b/engine/crates/layerfs-api/tests/mount_control.rs similarity index 99% rename from api/layerfs-api/tests/mount_control.rs rename to engine/crates/layerfs-api/tests/mount_control.rs index 880bddf55..fcd075faa 100644 --- a/api/layerfs-api/tests/mount_control.rs +++ b/engine/crates/layerfs-api/tests/mount_control.rs @@ -1,10 +1,10 @@ //! Authenticated control over an actually installed Store and one real owner. -#[path = "../../../engine/crates/layerfs-daemon/tests/support/control_fixture.rs"] +#[path = "../../layerfs-daemon/tests/support/control_fixture.rs"] mod fixture; -#[path = "../../../engine/crates/layerfs-daemon/tests/support/held_writer.rs"] +#[path = "../../layerfs-daemon/tests/support/held_writer.rs"] mod held_writer; #[allow(dead_code)] -#[path = "../../../engine/crates/layerfs-daemon/tests/support/host_install.rs"] +#[path = "../../layerfs-daemon/tests/support/host_install.rs"] mod support; use layerfs_api::{internal::Control, OperationCause}; use layerfs_bridge::control::{Activity, ControlCode, Reply, Request, WorkspaceToken}; diff --git a/api/layerfs-api/tests/observed_application.rs b/engine/crates/layerfs-api/tests/observed_application.rs similarity index 99% rename from api/layerfs-api/tests/observed_application.rs rename to engine/crates/layerfs-api/tests/observed_application.rs index 94b446e35..280904d3e 100644 --- a/api/layerfs-api/tests/observed_application.rs +++ b/engine/crates/layerfs-api/tests/observed_application.rs @@ -3,7 +3,7 @@ #[path = "support/daemon_binary.rs"] mod daemon_binary; #[allow(dead_code)] -#[path = "../../../engine/crates/layerfs-daemon/tests/support/host_install.rs"] +#[path = "../../layerfs-daemon/tests/support/host_install.rs"] mod support; use layerfs_api::internal::Control; #[cfg(target_os = "linux")] diff --git a/api/layerfs-api/tests/observed_control.rs b/engine/crates/layerfs-api/tests/observed_control.rs similarity index 100% rename from api/layerfs-api/tests/observed_control.rs rename to engine/crates/layerfs-api/tests/observed_control.rs diff --git a/api/layerfs-api/tests/operator_history.rs b/engine/crates/layerfs-api/tests/operator_history.rs similarity index 100% rename from api/layerfs-api/tests/operator_history.rs rename to engine/crates/layerfs-api/tests/operator_history.rs diff --git a/api/layerfs-api/tests/r5_1_actual_daemon_commit.rs b/engine/crates/layerfs-api/tests/r5_1_actual_daemon_commit.rs similarity index 97% rename from api/layerfs-api/tests/r5_1_actual_daemon_commit.rs rename to engine/crates/layerfs-api/tests/r5_1_actual_daemon_commit.rs index b73ec480a..be1a43155 100644 --- a/api/layerfs-api/tests/r5_1_actual_daemon_commit.rs +++ b/engine/crates/layerfs-api/tests/r5_1_actual_daemon_commit.rs @@ -21,19 +21,19 @@ #[path = "support/daemon_binary.rs"] mod daemon_binary; #[allow(dead_code)] -#[path = "../../../engine/crates/layerfs-daemon/tests/support/installed_store.rs"] +#[path = "../../layerfs-daemon/tests/support/installed_store.rs"] mod installed; #[allow(dead_code)] -#[path = "../../../engine/crates/layerfs-daemon/tests/support/namespace_model.rs"] +#[path = "../../layerfs-daemon/tests/support/namespace_model.rs"] mod model; #[allow(dead_code)] -#[path = "../../../engine/crates/layerfs-daemon/tests/support/mounted.rs"] +#[path = "../../layerfs-daemon/tests/support/mounted.rs"] mod mounted; #[allow(dead_code)] -#[path = "../../../engine/crates/layerfs-daemon/tests/support/mounted_commit.rs"] +#[path = "../../layerfs-daemon/tests/support/mounted_commit.rs"] mod rig; #[allow(dead_code)] -#[path = "../../../engine/crates/layerfs-daemon/tests/support/host_install.rs"] +#[path = "../../layerfs-daemon/tests/support/host_install.rs"] mod support; use layerfs_api::internal::Control; use layerfs_bridge::{ diff --git a/api/layerfs-api/tests/refresh_lookups.rs b/engine/crates/layerfs-api/tests/refresh_lookups.rs similarity index 100% rename from api/layerfs-api/tests/refresh_lookups.rs rename to engine/crates/layerfs-api/tests/refresh_lookups.rs diff --git a/api/layerfs-api/tests/relink_commit.rs b/engine/crates/layerfs-api/tests/relink_commit.rs similarity index 100% rename from api/layerfs-api/tests/relink_commit.rs rename to engine/crates/layerfs-api/tests/relink_commit.rs diff --git a/api/layerfs-api/tests/replay_merges.rs b/engine/crates/layerfs-api/tests/replay_merges.rs similarity index 100% rename from api/layerfs-api/tests/replay_merges.rs rename to engine/crates/layerfs-api/tests/replay_merges.rs diff --git a/api/layerfs-api/tests/sandbox_operations.rs b/engine/crates/layerfs-api/tests/sandbox_operations.rs similarity index 99% rename from api/layerfs-api/tests/sandbox_operations.rs rename to engine/crates/layerfs-api/tests/sandbox_operations.rs index 1b0828e69..64859816e 100644 --- a/api/layerfs-api/tests/sandbox_operations.rs +++ b/engine/crates/layerfs-api/tests/sandbox_operations.rs @@ -1,7 +1,7 @@ //! Bounded original Engine/control peers qualify SDK close custody and ordinary exec routing. #![cfg(unix)] #[allow(dead_code)] -#[path = "../../../engine/crates/layerfs-sandbox/tests/support/engine.rs"] +#[path = "../../layerfs-sandbox/tests/support/engine.rs"] mod engine; use engine::{fixed, frame, Peer}; use layerfs_api::{ diff --git a/api/layerfs-api/tests/scale_lineage_cap.rs b/engine/crates/layerfs-api/tests/scale_lineage_cap.rs similarity index 100% rename from api/layerfs-api/tests/scale_lineage_cap.rs rename to engine/crates/layerfs-api/tests/scale_lineage_cap.rs diff --git a/api/layerfs-api/tests/sdk_branch_count.rs b/engine/crates/layerfs-api/tests/sdk_branch_count.rs similarity index 100% rename from api/layerfs-api/tests/sdk_branch_count.rs rename to engine/crates/layerfs-api/tests/sdk_branch_count.rs diff --git a/api/layerfs-api/tests/sdk_chunk_deltas.rs b/engine/crates/layerfs-api/tests/sdk_chunk_deltas.rs similarity index 100% rename from api/layerfs-api/tests/sdk_chunk_deltas.rs rename to engine/crates/layerfs-api/tests/sdk_chunk_deltas.rs diff --git a/api/layerfs-api/tests/sdk_compare.rs b/engine/crates/layerfs-api/tests/sdk_compare.rs similarity index 100% rename from api/layerfs-api/tests/sdk_compare.rs rename to engine/crates/layerfs-api/tests/sdk_compare.rs diff --git a/api/layerfs-api/tests/sdk_diff_entries.rs b/engine/crates/layerfs-api/tests/sdk_diff_entries.rs similarity index 100% rename from api/layerfs-api/tests/sdk_diff_entries.rs rename to engine/crates/layerfs-api/tests/sdk_diff_entries.rs diff --git a/api/layerfs-api/tests/sdk_diff_pages.rs b/engine/crates/layerfs-api/tests/sdk_diff_pages.rs similarity index 100% rename from api/layerfs-api/tests/sdk_diff_pages.rs rename to engine/crates/layerfs-api/tests/sdk_diff_pages.rs diff --git a/api/layerfs-api/tests/sdk_diff_size.rs b/engine/crates/layerfs-api/tests/sdk_diff_size.rs similarity index 100% rename from api/layerfs-api/tests/sdk_diff_size.rs rename to engine/crates/layerfs-api/tests/sdk_diff_size.rs diff --git a/api/layerfs-api/tests/sdk_fixed_costs.rs b/engine/crates/layerfs-api/tests/sdk_fixed_costs.rs similarity index 100% rename from api/layerfs-api/tests/sdk_fixed_costs.rs rename to engine/crates/layerfs-api/tests/sdk_fixed_costs.rs diff --git a/api/layerfs-api/tests/sdk_fs_reads_replay.rs b/engine/crates/layerfs-api/tests/sdk_fs_reads_replay.rs similarity index 100% rename from api/layerfs-api/tests/sdk_fs_reads_replay.rs rename to engine/crates/layerfs-api/tests/sdk_fs_reads_replay.rs diff --git a/api/layerfs-api/tests/sdk_grep_reads.rs b/engine/crates/layerfs-api/tests/sdk_grep_reads.rs similarity index 100% rename from api/layerfs-api/tests/sdk_grep_reads.rs rename to engine/crates/layerfs-api/tests/sdk_grep_reads.rs diff --git a/api/layerfs-api/tests/sdk_history_depth.rs b/engine/crates/layerfs-api/tests/sdk_history_depth.rs similarity index 100% rename from api/layerfs-api/tests/sdk_history_depth.rs rename to engine/crates/layerfs-api/tests/sdk_history_depth.rs diff --git a/api/layerfs-api/tests/sdk_list_entries.rs b/engine/crates/layerfs-api/tests/sdk_list_entries.rs similarity index 100% rename from api/layerfs-api/tests/sdk_list_entries.rs rename to engine/crates/layerfs-api/tests/sdk_list_entries.rs diff --git a/api/layerfs-api/tests/sdk_merge_diagnostics.rs b/engine/crates/layerfs-api/tests/sdk_merge_diagnostics.rs similarity index 100% rename from api/layerfs-api/tests/sdk_merge_diagnostics.rs rename to engine/crates/layerfs-api/tests/sdk_merge_diagnostics.rs diff --git a/api/layerfs-api/tests/sdk_merge_paths.rs b/engine/crates/layerfs-api/tests/sdk_merge_paths.rs similarity index 100% rename from api/layerfs-api/tests/sdk_merge_paths.rs rename to engine/crates/layerfs-api/tests/sdk_merge_paths.rs diff --git a/api/layerfs-api/tests/sdk_merge_scale.rs b/engine/crates/layerfs-api/tests/sdk_merge_scale.rs similarity index 100% rename from api/layerfs-api/tests/sdk_merge_scale.rs rename to engine/crates/layerfs-api/tests/sdk_merge_scale.rs diff --git a/api/layerfs-api/tests/sdk_method_golden.rs b/engine/crates/layerfs-api/tests/sdk_method_golden.rs similarity index 100% rename from api/layerfs-api/tests/sdk_method_golden.rs rename to engine/crates/layerfs-api/tests/sdk_method_golden.rs diff --git a/api/layerfs-api/tests/sdk_mount_lookup.rs b/engine/crates/layerfs-api/tests/sdk_mount_lookup.rs similarity index 100% rename from api/layerfs-api/tests/sdk_mount_lookup.rs rename to engine/crates/layerfs-api/tests/sdk_mount_lookup.rs diff --git a/api/layerfs-api/tests/sdk_project_count.rs b/engine/crates/layerfs-api/tests/sdk_project_count.rs similarity index 100% rename from api/layerfs-api/tests/sdk_project_count.rs rename to engine/crates/layerfs-api/tests/sdk_project_count.rs diff --git a/api/layerfs-api/tests/sdk_reads_during_publish.rs b/engine/crates/layerfs-api/tests/sdk_reads_during_publish.rs similarity index 100% rename from api/layerfs-api/tests/sdk_reads_during_publish.rs rename to engine/crates/layerfs-api/tests/sdk_reads_during_publish.rs diff --git a/api/layerfs-api/tests/sdk_reads_under_publish.rs b/engine/crates/layerfs-api/tests/sdk_reads_under_publish.rs similarity index 100% rename from api/layerfs-api/tests/sdk_reads_under_publish.rs rename to engine/crates/layerfs-api/tests/sdk_reads_under_publish.rs diff --git a/api/layerfs-api/tests/sdk_text_scan.rs b/engine/crates/layerfs-api/tests/sdk_text_scan.rs similarity index 100% rename from api/layerfs-api/tests/sdk_text_scan.rs rename to engine/crates/layerfs-api/tests/sdk_text_scan.rs diff --git a/api/layerfs-api/tests/sdk_timing_coverage.rs b/engine/crates/layerfs-api/tests/sdk_timing_coverage.rs similarity index 100% rename from api/layerfs-api/tests/sdk_timing_coverage.rs rename to engine/crates/layerfs-api/tests/sdk_timing_coverage.rs diff --git a/api/layerfs-api/tests/sdk_written_back.rs b/engine/crates/layerfs-api/tests/sdk_written_back.rs similarity index 100% rename from api/layerfs-api/tests/sdk_written_back.rs rename to engine/crates/layerfs-api/tests/sdk_written_back.rs diff --git a/api/layerfs-api/tests/support/daemon_binary.rs b/engine/crates/layerfs-api/tests/support/daemon_binary.rs similarity index 100% rename from api/layerfs-api/tests/support/daemon_binary.rs rename to engine/crates/layerfs-api/tests/support/daemon_binary.rs diff --git a/api/layerfs-api/tests/support/installed_store.rs b/engine/crates/layerfs-api/tests/support/installed_store.rs similarity index 100% rename from api/layerfs-api/tests/support/installed_store.rs rename to engine/crates/layerfs-api/tests/support/installed_store.rs diff --git a/api/layerfs-api/tests/support/sdk.rs b/engine/crates/layerfs-api/tests/support/sdk.rs similarity index 100% rename from api/layerfs-api/tests/support/sdk.rs rename to engine/crates/layerfs-api/tests/support/sdk.rs diff --git a/api/layerfs-api/tests/support/view.rs b/engine/crates/layerfs-api/tests/support/view.rs similarity index 100% rename from api/layerfs-api/tests/support/view.rs rename to engine/crates/layerfs-api/tests/support/view.rs diff --git a/api/layerfs-api/tests/workspace_reader_cache.rs b/engine/crates/layerfs-api/tests/workspace_reader_cache.rs similarity index 100% rename from api/layerfs-api/tests/workspace_reader_cache.rs rename to engine/crates/layerfs-api/tests/workspace_reader_cache.rs diff --git a/api/layerfs-api/tests/write_cost.rs b/engine/crates/layerfs-api/tests/write_cost.rs similarity index 100% rename from api/layerfs-api/tests/write_cost.rs rename to engine/crates/layerfs-api/tests/write_cost.rs diff --git a/api/layerfs-api/tests/write_refusals.rs b/engine/crates/layerfs-api/tests/write_refusals.rs similarity index 100% rename from api/layerfs-api/tests/write_refusals.rs rename to engine/crates/layerfs-api/tests/write_refusals.rs diff --git a/engine/crates/layerfs-node/Cargo.toml b/engine/crates/layerfs-node/Cargo.toml new file mode 100644 index 000000000..44fca5220 --- /dev/null +++ b/engine/crates/layerfs-node/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "layerfs-node" +description = "Node binding for the LayerFS JavaScript SDK: Store calls in-process (layerfs-store-service), Sandbox calls over layerfs-api" +publish = false +workspace = "../../.." +edition.workspace = true +version.workspace = true +rust-version.workspace = true +license.workspace = true + +[lib] +crate-type = ["cdylib"] +path = "src/lib.rs" + +[dependencies] +layerfs-project = { path = "../layerfs-project" } +layerfs-api = { path = "../layerfs-api" } +layerfs-bridge = { path = "../layerfs-bridge" } +layerfs-history = { path = "../../../core/crates/layerfs-history" } +layerfs-persistence = { path = "../layerfs-persistence" } +layerfs-sandbox = { path = "../layerfs-sandbox" } +layerfs-storage = { path = "../../../core/crates/layerfs-storage" } +layerfs-store-service = { path = "../layerfs-store-service" } +layerfs-telemetry = { path = "../../../core/crates/layerfs-telemetry" } +napi = "=2.16.17" +napi-derive = "=2.16.13" + +[build-dependencies] +napi-build = "=2.1.6" diff --git a/api/binding/build.rs b/engine/crates/layerfs-node/build.rs similarity index 100% rename from api/binding/build.rs rename to engine/crates/layerfs-node/build.rs diff --git a/api/binding/examples/restore_record.rs b/engine/crates/layerfs-node/examples/restore_record.rs similarity index 100% rename from api/binding/examples/restore_record.rs rename to engine/crates/layerfs-node/examples/restore_record.rs diff --git a/api/binding/src/convert.rs b/engine/crates/layerfs-node/src/convert.rs similarity index 100% rename from api/binding/src/convert.rs rename to engine/crates/layerfs-node/src/convert.rs diff --git a/api/binding/src/direct.rs b/engine/crates/layerfs-node/src/direct.rs similarity index 100% rename from api/binding/src/direct.rs rename to engine/crates/layerfs-node/src/direct.rs diff --git a/api/binding/src/discovery.rs b/engine/crates/layerfs-node/src/discovery.rs similarity index 100% rename from api/binding/src/discovery.rs rename to engine/crates/layerfs-node/src/discovery.rs diff --git a/api/binding/src/dispatch.rs b/engine/crates/layerfs-node/src/dispatch.rs similarity index 100% rename from api/binding/src/dispatch.rs rename to engine/crates/layerfs-node/src/dispatch.rs diff --git a/api/binding/src/exec.rs b/engine/crates/layerfs-node/src/exec.rs similarity index 100% rename from api/binding/src/exec.rs rename to engine/crates/layerfs-node/src/exec.rs diff --git a/api/binding/src/job.rs b/engine/crates/layerfs-node/src/job.rs similarity index 100% rename from api/binding/src/job.rs rename to engine/crates/layerfs-node/src/job.rs diff --git a/api/binding/src/lib.rs b/engine/crates/layerfs-node/src/lib.rs similarity index 100% rename from api/binding/src/lib.rs rename to engine/crates/layerfs-node/src/lib.rs diff --git a/api/binding/src/output.rs b/engine/crates/layerfs-node/src/output.rs similarity index 100% rename from api/binding/src/output.rs rename to engine/crates/layerfs-node/src/output.rs diff --git a/api/binding/src/pool.rs b/engine/crates/layerfs-node/src/pool.rs similarity index 100% rename from api/binding/src/pool.rs rename to engine/crates/layerfs-node/src/pool.rs diff --git a/api/binding/src/project.rs b/engine/crates/layerfs-node/src/project.rs similarity index 100% rename from api/binding/src/project.rs rename to engine/crates/layerfs-node/src/project.rs diff --git a/api/binding/src/registry.rs b/engine/crates/layerfs-node/src/registry.rs similarity index 100% rename from api/binding/src/registry.rs rename to engine/crates/layerfs-node/src/registry.rs diff --git a/api/binding/src/sandbox.rs b/engine/crates/layerfs-node/src/sandbox.rs similarity index 100% rename from api/binding/src/sandbox.rs rename to engine/crates/layerfs-node/src/sandbox.rs diff --git a/api/binding/src/trace.rs b/engine/crates/layerfs-node/src/trace.rs similarity index 100% rename from api/binding/src/trace.rs rename to engine/crates/layerfs-node/src/trace.rs diff --git a/api/binding/src/workspace.rs b/engine/crates/layerfs-node/src/workspace.rs similarity index 100% rename from api/binding/src/workspace.rs rename to engine/crates/layerfs-node/src/workspace.rs diff --git a/api/binding/tests/README.md b/engine/crates/layerfs-node/tests/README.md similarity index 100% rename from api/binding/tests/README.md rename to engine/crates/layerfs-node/tests/README.md diff --git a/api/binding/tests/native_admission.rs b/engine/crates/layerfs-node/tests/native_admission.rs similarity index 100% rename from api/binding/tests/native_admission.rs rename to engine/crates/layerfs-node/tests/native_admission.rs diff --git a/api/binding/tests/native_discovery.rs b/engine/crates/layerfs-node/tests/native_discovery.rs similarity index 100% rename from api/binding/tests/native_discovery.rs rename to engine/crates/layerfs-node/tests/native_discovery.rs diff --git a/api/binding/tests/support/engine.rs b/engine/crates/layerfs-node/tests/support/engine.rs similarity index 100% rename from api/binding/tests/support/engine.rs rename to engine/crates/layerfs-node/tests/support/engine.rs diff --git a/api/binding/tests/support/fork_lock.c b/engine/crates/layerfs-node/tests/support/fork_lock.c similarity index 100% rename from api/binding/tests/support/fork_lock.c rename to engine/crates/layerfs-node/tests/support/fork_lock.c diff --git a/api/binding/tests/support/mod.rs b/engine/crates/layerfs-node/tests/support/mod.rs similarity index 100% rename from api/binding/tests/support/mod.rs rename to engine/crates/layerfs-node/tests/support/mod.rs diff --git a/plugins/dsh-layerfs/install.md b/plugins/dsh-layerfs/install.md index ee0adba2a..300af2f97 100644 --- a/plugins/dsh-layerfs/install.md +++ b/plugins/dsh-layerfs/install.md @@ -12,7 +12,7 @@ Rules: Install: 1. Prerequisites; record each version. All: Node 22.19 or newer, pnpm, python3, Docker, network access, and a built deepseek-harness checkout (https://github.com/deepseek-ai/deepseek-harness) beside the plugin, with a dsh version inside the plugin's packages/dsh-layerfs/package.json engines.dsh; if there is none, clone it there and run pnpm install && pnpm run build in it. macOS: Docker Desktop running. Linux: a Docker Engine, /dev/fuse, and a Store filesystem that is ext4, xfs or btrfs. Windows: WSL2 with a selected distribution (default Ubuntu) that has /dev/fuse, its own running Docker Engine (not Docker Desktop's Windows pipe), and Node 22.19 or newer at an absolute path. Keep at least 20 GiB free inside that Docker Engine. If something is missing that you cannot install, stop and tell me which. -2. LayerFS checkouts at {{layerfs.commit}}: one on macOS or Linux; on Windows two of the same commit, one in WSL for the sealed bundle and one on Windows for the dsh Host (record core.autocrlf: the worker refuses a Windows SDK that differs from the bundle's, apart from line endings). In the checkout the Host uses, run npm install in api and npm --prefix api/agent/cli install; they only link packages. +2. LayerFS checkouts at {{layerfs.commit}}: one on macOS or Linux; on Windows two of the same commit, one in WSL for the sealed bundle and one on Windows for the dsh Host (record core.autocrlf: the worker refuses a Windows SDK that differs from the bundle's, apart from line endings). In the checkout the Host uses, run npm install in api and npm --prefix api/cli install; they only link packages. 3. Runtime image: build it from the plugin's tools/runtime/Dockerfile in the Docker Engine the worker and Sandboxes use (on Windows, the WSL one), and record its sha256 image ID. Check it has cargo (docker run --rm cargo --version): the Depot scenario needs it. 4. LayerFS build. macOS and Windows: build the sealed Linux bundle with the LayerFS checkout's tools/worktree.py (register, prepare, build --platform linux --profile release; see docs/general/parallel-worktrees.md), on Windows inside WSL; record the printed build-linux-… folder and its manifest.json hash, and confirm it holds api/runtime/src/worker/server.js, layerfs-daemon and layerfs.node. Linux: build layerfs-daemon and the addon (the plugin README's step 1 recipe, or npm --prefix api run build:native), and record the daemon path and the layerfs.node dsh web will load. 5. Plugin: in the dsh-layerfs checkout, with LAYERFS_SOURCE set to the Host's LayerFS checkout, run pnpm install, then pnpm run link:layerfs, then pnpm run build with DSH_SOURCE set to the deepseek-harness checkout (absolute paths). pnpm run check:layerfs must report the checkout "at the pinned commit". diff --git a/plugins/magpie-layerfs/install.md b/plugins/magpie-layerfs/install.md index 4f1a39137..b00f1e99f 100644 --- a/plugins/magpie-layerfs/install.md +++ b/plugins/magpie-layerfs/install.md @@ -1,9 +1,9 @@ Install LayerFS for Magpie {{version}} for me. 1. Clone https://github.com/Ephemeral-AI-Lab/layerfs beside this repository and check out commit {{layerfs.commit}} ({{layerfs.version}}). Use exactly this commit: it is the one this version was tested with. -2. Build the LayerFS native binding in that checkout: run `npm --prefix api install` (it only links the workspace packages and downloads nothing), then `npm --prefix api run build:native`. This needs a Rust toolchain (Cargo) and produces `api/binding/layerfs.node`. If the build fails, stop and report the error. +2. Build the LayerFS native binding in that checkout: run `npm --prefix api install` (it only links the workspace packages and downloads nothing), then `npm --prefix api run build:native`. This needs a Rust toolchain (Cargo) and produces `engine/crates/layerfs-node/layerfs.node`. If the build fails, stop and report the error. 3. Clone {{repository}} beside it and check out commit {{commit}}. -4. Check the plugin against the real SDK: in the plugin checkout, set `LAYERFS_SDK_PATH` to the LayerFS checkout's `api/agent/sdk/src/index.js`, set `MAGPIE_LAYERFS_NATIVE_TEST=1`, and run `bun test`. Expected: 59 pass, 0 fail. (A plain `bun test` without those variables gives 56 pass and 3 skip; that is the sim side only.) +4. Check the plugin against the real SDK: in the plugin checkout, set `LAYERFS_SDK_PATH` to the LayerFS checkout's `api/agent/src/index.js`, set `MAGPIE_LAYERFS_NATIVE_TEST=1`, and run `bun test`. Expected: 59 pass, 0 fail. (A plain `bun test` without those variables gives 56 pass and 3 skip; that is the sim side only.) 5. Install the plugin into Magpie from this checkout — the package is `@magpie-community/tools-layerfs`, and its registry build is sim-only, so the native backend comes from this checkout — then configure the host: set `LAYERFS_SDK_PATH` (the same path as in step 4) in the environment of the Magpie plugin host, and enable the plugin's `native` option (or set `MAGPIE_LAYERFS_NATIVE=1`). Leave the `exec` option off unless I ask for it. 6. Restart Magpie and ask an agent to call `layerfs_status`: it should report the native backend. If it reports sim, the opt-in or `LAYERFS_SDK_PATH` did not reach the host; tell me which one is missing. diff --git a/tools/check_product_boundary.py b/tools/check_product_boundary.py index 1a262b9d2..c4159c3c1 100644 --- a/tools/check_product_boundary.py +++ b/tools/check_product_boundary.py @@ -141,8 +141,10 @@ "layerfs-sandbox": ENGINE, "layerfs-store-service": ENGINE, "layerfs-workspace": ENGINE, - "layerfs-api": API, - "layerfs-node": API, + # The SDK method surface and the Node binding are engine crates; api/ holds + # only the published JavaScript packages, so no crate is in the api layer. + "layerfs-api": ENGINE, + "layerfs-node": ENGINE, } @@ -312,12 +314,6 @@ def crate_name(path): if parts[index + 1] == "layerfs-api" and index + 2 < len(parts) and parts[index + 2] == "core": return "layerfs-api-core" return parts[index + 1] - for index, part in enumerate(parts): - if part == "api" and index + 1 < len(parts): - if parts[index + 1] == "binding": - return "layerfs-node" - if parts[index + 1] == "layerfs-api": - return "layerfs-api" return None @@ -401,7 +397,7 @@ def production_files(root, include_sdk=True): """Known product inputs; tests/examples/tools are deliberately outside this scope.""" files = set() for package in crate_directories(root): - if not include_sdk and package == root / "api/binding": + if not include_sdk and package == root / "engine/crates/layerfs-node": continue if not package.is_dir(): continue @@ -411,8 +407,8 @@ def production_files(root, include_sdk=True): return sorted(files) api = root / "api" for directory in ( - api / "agent" / "sdk" / "src", - api / "agent" / "cli" / "src", + api / "agent" / "src", + api / "cli" / "src", api / "backend" / "src", api / "runtime" / "src", ): @@ -421,7 +417,7 @@ def production_files(root, include_sdk=True): def main(): - # --skip-sdk leaves api/ (binding and JS packages) out of the scan; CI uses it (owner, 2026-10-23). + # --skip-sdk leaves the Node binding and api/'s JS packages out of the scan; CI uses it (owner, 2026-10-23). root = Path(__file__).resolve().parents[1] files = production_files(root, include_sdk="--skip-sdk" not in sys.argv[1:]) failures = 0 diff --git a/tools/production_loc.py b/tools/production_loc.py index 1086aeef2..3341e4d03 100755 --- a/tools/production_loc.py +++ b/tools/production_loc.py @@ -2,23 +2,24 @@ """Count first-party production source lines for the per-commit LOC rule. Production code is nonblank, non-comment first-party product implementation: -the product under core/crates/*/src, engine/crates/*/src and api/layerfs-api/src, -and the reference product under crates/*/src, plus shipped runtime SQL under +the product under core/crates/*/src and engine/crates/*/src (layerfs-api and the +layerfs-node binding were api/layerfs-api and api/binding before the api/ +regrouping, and are counted there too), and the reference product under crates/*/src, plus shipped runtime SQL under /sql/. Tests, examples, benches, fixtures, benchmark harnesses, development tools, docs, manifests and generated artifacts are excluded. Legacy inline #[cfg(test)] items are removed before counting, because the reference tree keeps tests inside src/. -Rust crates are assigned by name to core, engine or api in both the old and -new layouts. Unknown historical crates remain counted in core. +Rust crates are assigned by name to core or engine in every layout: the +layerfs-api method surface and the layerfs-node binding are engine crates +wherever they sit. Unknown historical crates remain counted in core. -The JavaScript API shares the `api` scope (#428): the Node binding's Rust -under api/binding/src (layerfs-node) and the src/ JavaScript of each package -under api/ (api/agent/sdk is @layerfs/agent, api/agent/cli is @layerfs/cli, -api/backend and api/runtime), one crate per package, named by its -package.json. Tests, node_modules and the binding's tests/examples are -excluded. The layouts before the move to api/ are still counted, so trees on -either side compare: sdk/js/native/src, sdk/js/packages//src, the +The `api` scope is the published JavaScript (#428): the src/ JavaScript of +each package under api/ (api/agent is @layerfs/agent, api/cli is @layerfs/cli, +api/backend and api/runtime; api/agent/sdk and api/agent/cli before the +regrouping), one crate per package, named by its package.json. Tests and +node_modules are excluded. The layouts before the move to api/ are still +counted, so trees on either side compare: sdk/js/native/src, sdk/js/packages//src, the older single package @layerfs/sdk under sdk/js/src and sdk/js/operator, and the layerfs command under cli/src. Those were the separate `sdk` and `cli` scopes. JavaScript comments are blanked by a scanner that knows line and @@ -362,12 +363,14 @@ def counted_lines(path: Path) -> int: "layerfs-sandbox", "layerfs-store-service", "layerfs-workspace", + "layerfs-api", + "layerfs-node", } +# Crate folders directly under api/ before the regrouping, by folder name. +OLD_API_CRATES = {"layerfs-api": "layerfs-api", "binding": "layerfs-node"} def crate_layer(name: str) -> str: - if name == "layerfs-api": - return "api" if name in ENGINE_CRATES: return "engine" # Historical and synthetic crates remain counted rather than disappearing. @@ -377,10 +380,15 @@ def crate_layer(name: str) -> str: def replacement_packages(root: Path) -> list: return sorted( [p for base in (root / "core/crates", root / "engine/crates") for p in base.glob("*") if p.is_dir()] - + ([root / "api/layerfs-api"] if (root / "api/layerfs-api").is_dir() else []) + + [root / "api" / folder for folder in OLD_API_CRATES if (root / "api" / folder).is_dir()] ) +def package_crate(root: Path, package: Path) -> str: + """The crate name of a package folder; api/binding was layerfs-node.""" + return OLD_API_CRATES[package.name] if package.parent == root / "api" else package.name + + def scope_base(root: Path, scope: str) -> Path: if scope in {"core", "engine"}: return root @@ -409,8 +417,6 @@ def api_files(root: Path) -> list: """The binding's Rust and each package's src/ JavaScript, in either layout.""" files = [] api = root / "api" - if (api / "binding" / "src").is_dir(): - files += kept(sorted((api / "binding" / "src").rglob("*.rs")), api / "binding") if api.is_dir(): for package in api_packages(api): files += kept(sorted((package / "src").rglob("*.js")), package) @@ -431,9 +437,7 @@ def api_files(root: Path) -> list: def api_crate(root: Path, path: Path) -> str: parts = path.relative_to(root).parts - if "layerfs-api" in parts: - return "layerfs-api" - if parts[:2] == ("api", "binding") or parts[:3] == ("sdk", "js", "native"): + if parts[:3] == ("sdk", "js", "native"): return "layerfs-node" if parts[0] == "cli": return "@layerfs/cli" @@ -466,7 +470,9 @@ def crate_of(root: Path, scope: str, path: Path) -> str: if scope == "dsh": return dsh_crate(base, path) parts = path.relative_to(root).parts - return parts[2] if scope in {"core", "engine"} else parts[1] + if scope in {"core", "engine"}: + return OLD_API_CRATES[parts[1]] if parts[0] == "api" else parts[2] + return parts[1] def rust_files(base: Path) -> list: @@ -499,7 +505,9 @@ def scope_files(root: Path, scope: str) -> list: packages = replacement_packages(root) for base in sorted({package.parent for package in packages}): names = { - package.name for package in packages if package.parent == base and crate_layer(package.name) == scope + package.name + for package in packages + if package.parent == base and crate_layer(package_crate(root, package)) == scope } files.extend(path for path in rust_files(base) if path.relative_to(base).parts[0] in names) if scope == "api": diff --git a/tools/test_check_product_boundary.py b/tools/test_check_product_boundary.py index 00b86800e..ec4196fbf 100644 --- a/tools/test_check_product_boundary.py +++ b/tools/test_check_product_boundary.py @@ -2,7 +2,9 @@ import unittest from pathlib import Path from tempfile import TemporaryDirectory +from unittest import mock +import check_product_boundary from check_product_boundary import ( RETIRED_PACKAGES, crate_directories, @@ -113,11 +115,11 @@ def test_retired_packages_cannot_return(self): self.assertTrue(dependency_violations(f'[package]\nname="{name}"\n'), name) def test_sdk_source_edges_and_unsafe_boundary(self): - path = Path("api/layerfs-api/src/project/init.rs") + path = Path("engine/crates/layerfs-api/src/project/init.rs") self.assertFalse(violations(path, "use layerfs_persistence::Handles;")) self.assertTrue(violations(path, "use layerfs_server::Server;")) self.assertTrue(unsafe_violations(path, "unsafe fn extend_lifetime() {}")) - root = Path("api/layerfs-api/src/lib.rs") + root = Path("engine/crates/layerfs-api/src/lib.rs") self.assertTrue(unsafe_violations(root, "mod init;")) self.assertFalse(unsafe_violations(root, "#![forbid(unsafe_code)]\nmod init;")) @@ -172,7 +174,7 @@ def test_daemon_direct_store_and_control_edges_without_host_runtime(self): self.assertTrue(violations(path, "use layerfs_api::Runtime;")) sdk = '[package]\nname="layerfs-api"\n[dependencies]\n' self.assertTrue(dependency_violations(sdk + 'layerfs-daemon={path="../../layerfs-daemon"}')) - self.assertTrue(violations(Path("api/layerfs-api/src/project/init.rs"), "use layerfs_daemon::Owner;")) + self.assertTrue(violations(Path("engine/crates/layerfs-api/src/project/init.rs"), "use layerfs_daemon::Owner;")) def test_store_service_engine_edges(self): prefix = '[package]\nname="layerfs-store-service"\n[dependencies]\n' @@ -200,7 +202,7 @@ def test_workspace_composition_edges_preserve_domain_and_reverse_boundaries(self source = f'[package]\nname="{package}"\n[dependencies]\nlayerfs-workspace={{path="../layerfs-workspace"}}\n' self.assertEqual(bool(dependency_violations(source)), package == "layerfs-api") path = ( - Path("api/layerfs-api/src/project/init.rs") + Path("engine/crates/layerfs-api/src/project/init.rs") if package == "layerfs-api" else Path("engine/crates/layerfs-daemon/src/commands.rs") ) @@ -224,10 +226,11 @@ def test_cluster1_dependency_edges(self): source = f'[package]\nname="{package}"\n[{table}]\nrenamed={{package="{dependency}",path="../{dependency}"}}\n' self.assertTrue(dependency_violations(source)) source = f'[package]\nname="{package}"\n[dev-dependencies]\n"{dependency}"={{path="../{dependency}"}}\n' - # Dev edges now obey layers too; project -> workspace stays within engine. + # Dev edges now obey layers too; project -> workspace and project -> + # layerfs-api stay within engine. self.assertEqual( bool(dependency_violations(source)), - not (package == "layerfs-project" and dependency == "layerfs-workspace"), + not (package == "layerfs-project" and dependency in ("layerfs-workspace", "layerfs-api")), ) self.assertFalse( dependency_violations( @@ -388,7 +391,7 @@ def test_shipped_sql_and_external_tests_scope(self): def test_flat_api_product_scope(self): with TemporaryDirectory() as directory: root = Path(directory) - package = root / "api/layerfs-api" + package = root / "engine/crates/layerfs-api" for name in ("src/lib.rs", "src/fs/read.rs", "tests/route.rs", "examples/demo.rs"): path = package / name path.parent.mkdir(parents=True, exist_ok=True) @@ -406,7 +409,7 @@ def test_crate_discovery_covers_all_layers_and_unknown_packages(self): for relative, name in ( ("core/crates/layerfs-content", "layerfs-content"), ("engine/crates/layerfs-project", "layerfs-project"), - ("api/binding", "layerfs-node"), + ("engine/crates/layerfs-node", "layerfs-node"), ("api/layerfs-new", "layerfs-new"), ): package = root / relative @@ -423,15 +426,15 @@ def test_skip_sdk_leaves_only_the_sdk_out(self): core = root / "core" for path in ( core / "crates/store/src/lib.rs", - root / "api/binding/src/lib.rs", - root / "api/agent/sdk/src/index.js", + root / "engine/crates/layerfs-node/src/lib.rs", + root / "api/agent/src/index.js", ): path.parent.mkdir(parents=True, exist_ok=True) path.write_text("") - (root / "api/binding/Cargo.toml").write_text('[package]\nname="layerfs-node"\n') + (root / "engine/crates/layerfs-node/Cargo.toml").write_text('[package]\nname="layerfs-node"\n') everything = [str(p.relative_to(root)) for p in production_files(core.parent)] - self.assertIn("api/binding/src/lib.rs", everything) - self.assertIn("api/agent/sdk/src/index.js", everything) + self.assertIn("engine/crates/layerfs-node/src/lib.rs", everything) + self.assertIn("api/agent/src/index.js", everything) self.assertEqual( [str(p.relative_to(root)) for p in production_files(core.parent, include_sdk=False)], ["core/crates/store/src/lib.rs"], @@ -451,15 +454,21 @@ def test_production_and_build_edges_obey_layers(self): if upward: self.assertTrue(any("upward" in reason for _, reason in dependency_violations(source))) + # No Rust crate sits in the api layer (layerfs-api and layerfs-node are engine + # crates), so upward-edge checks use a stand-in api crate. + @mock.patch.dict(check_product_boundary.LAYER, {"layerfs-mcp": "api"}) def test_dev_edges_reject_all_upward_dependencies(self): for table in ("dev-dependencies", "target.'cfg(unix)'.dev-dependencies"): for name, dependency, upward in ( ("layerfs-content", "layerfs-storage", False), ("layerfs-content", "layerfs-project", True), + ("layerfs-content", "layerfs-api", True), ("layerfs-project", "layerfs-workspace", False), - ("layerfs-daemon", "layerfs-api", True), - ("layerfs-workspace", "layerfs-api", True), + ("layerfs-daemon", "layerfs-api", False), + ("layerfs-daemon", "layerfs-mcp", True), + ("layerfs-workspace", "layerfs-mcp", True), ("layerfs-node", "layerfs-api", False), + ("layerfs-node", "layerfs-mcp", True), ): with self.subTest(table=table, name=name, dependency=dependency): source = f'[package]\nname="{name}"\n[{table}]\nrenamed={{package="{dependency}"}}' @@ -476,6 +485,7 @@ def test_core_rejects_sqlite_in_every_dependency_kind(self): dependency_violations('[package]\nname="layerfs-persistence"\n[dev-dependencies]\nrusqlite="1"') ) + @mock.patch.dict(check_product_boundary.LAYER, {"layerfs-mcp": "api"}) def test_path_escape_rejects_all_upward_includes(self): with TemporaryDirectory() as directory: core = Path(directory) / "core" @@ -485,7 +495,7 @@ def test_path_escape_rejects_all_upward_includes(self): "layerfs-content", "layerfs-storage", "layerfs-daemon", - "layerfs-api", + "layerfs-mcp", ) } content, storage, daemon, api = packages diff --git a/tools/test_ci_tests.py b/tools/test_ci_tests.py index 1c8476a10..21c4c7a8e 100644 --- a/tools/test_ci_tests.py +++ b/tools/test_ci_tests.py @@ -58,12 +58,12 @@ def test_binding_tests_stay_out_of_the_ci_lanes(self): { "name": "native_discovery", "kind": ["test"], - "src_path": "/w/api/binding/tests/native_discovery.rs", + "src_path": "/w/engine/crates/layerfs-node/tests/native_discovery.rs", }, { "name": "native_admission", "kind": ["test"], - "src_path": "/w/api/binding/tests/native_admission.rs", + "src_path": "/w/engine/crates/layerfs-node/tests/native_admission.rs", }, ], } diff --git a/tools/test_production_loc.py b/tools/test_production_loc.py index 0d5e3b6d5..318b8da9e 100644 --- a/tools/test_production_loc.py +++ b/tools/test_production_loc.py @@ -35,20 +35,52 @@ def test_layer_classification_survives_relocation(self): shutil.move(self.root / "core/crates/layerfs-api", self.root / "api/layerfs-api") after = production_loc.scan(self.root) self.assertEqual(before, after) - for layer, name in (("core", "layerfs-content"), ("engine", "layerfs-project"), ("api", "layerfs-api")): - self.assertEqual(after["scopes"][layer]["crates"], {name: 2}) + self.assertEqual(after["scopes"]["core"]["crates"], {"layerfs-content": 2}) + # layerfs-api is an engine crate wherever it sits. + self.assertEqual(after["scopes"]["engine"]["crates"], {"layerfs-project": 2, "layerfs-api": 2}) + shutil.move(self.root / "api/layerfs-api", self.root / "engine/crates/layerfs-api") + self.assertEqual(production_loc.scan(self.root), after) + + def test_api_regrouping_keeps_every_crate_and_count(self): + import shutil + + write(self.root, "engine/crates/layerfs-daemon/src/lib.rs", "pub fn value() {}\n") + write(self.root, "api/layerfs-api/src/lib.rs", "pub fn value() {}\n") + write(self.root, "api/binding/src/lib.rs", "pub fn value() {}\npub fn other() {}\n") + for folder, name in ( + ("agent/sdk", "@layerfs/agent"), + ("agent/cli", "@layerfs/cli"), + ("backend", "@layerfs/backend"), + ): + write(self.root, f"api/{folder}/package.json", f'{{"name": "{name}"}}\n') + write(self.root, f"api/{folder}/src/index.js", "export const value = 1;\n") + before = production_loc.scan(self.root) + shutil.move(self.root / "api/layerfs-api", self.root / "engine/crates/layerfs-api") + shutil.move(self.root / "api/binding", self.root / "engine/crates/layerfs-node") + shutil.move(self.root / "api/agent/cli", self.root / "api/cli") + shutil.move(self.root / "api/agent/sdk", self.root / "api/agent-sdk") + (self.root / "api/agent").rmdir() + shutil.move(self.root / "api/agent-sdk", self.root / "api/agent") + after = production_loc.scan(self.root) + self.assertEqual(before, after) + self.assertEqual( + after["scopes"]["engine"]["crates"], {"layerfs-daemon": 1, "layerfs-api": 1, "layerfs-node": 2} + ) + self.assertEqual( + after["scopes"]["api"]["crates"], {"@layerfs/agent": 1, "@layerfs/cli": 1, "@layerfs/backend": 1} + ) def test_nested_api_members_count_only_product_source(self): for name in ("core/src/lib.rs", "sdk/src/client.rs", "sdk/tests/route.rs", "mcp/src/lib.rs", "cli/src/main.rs"): write(self.root, f"core/crates/layerfs-api/{name}", "pub fn value() {}\n") - files = production_loc.scope_files(self.root, "api") + files = production_loc.scope_files(self.root, "engine") self.assertEqual( [str(path.relative_to(self.root / "core/crates/layerfs-api")) for path in files], ["core/src/lib.rs", "sdk/src/client.rs"], ) - self.assertEqual(production_loc.scan(self.root)["scopes"]["api"]["lines"], 2) + self.assertEqual(production_loc.scan(self.root)["scopes"]["engine"]["lines"], 2) - def test_api_counts_the_binding_and_each_package_by_its_name(self): + def test_api_counts_each_package_by_its_name_and_the_binding_as_engine(self): write(self.root, "api/package.json", '{"name": "layerfs-js"}\n') for folder, name in ( ("agent/sdk", "@layerfs/agent"), @@ -74,24 +106,25 @@ def test_api_counts_the_binding_and_each_package_by_its_name(self): "agent/sdk/src/index.js", "backend/src/index.js", "backend/src/store/get.js", - "binding/src/lib.rs", "runtime/src/index.js", ], ) - scope = production_loc.scan(self.root)["scopes"]["api"] + scan = production_loc.scan(self.root) + scope = scan["scopes"]["api"] self.assertEqual( (scope["lines"], scope["crates"]), ( - 6, + 5, { "@layerfs/agent": 1, "@layerfs/backend": 2, "@layerfs/cli": 1, "@layerfs/runtime": 1, - "layerfs-node": 1, }, ), ) + # The binding's Rust is an engine crate, tests and examples excluded. + self.assertEqual(scan["scopes"]["engine"]["crates"], {"layerfs-node": 1}) def test_api_still_counts_the_layouts_before_the_move(self): """sdk/js and cli/ (the former `sdk` and `cli` scopes) count as `api`.""" diff --git a/tools/test_worktree.py b/tools/test_worktree.py index df5d12258..69cfac928 100644 --- a/tools/test_worktree.py +++ b/tools/test_worktree.py @@ -30,19 +30,19 @@ def setUp(self): "core/crates/example/src", "engine/vendor", "engine/crates/example/src", - "api/layerfs-api/src", + "engine/crates/layerfs-api/src", ".cargo", - "api/agent/sdk/src", - "api/agent/sdk/test", + "api/agent/src", + "api/agent/test", "api/backend/src", "api/runtime/src", - "api/binding/src", + "engine/crates/layerfs-node/src", ): (self.repo / folder).mkdir(parents=True) for name in ("Cargo.toml", "Cargo.lock", ".cargo/config.toml", "api/package.json"): (self.repo / name).write_text("{}\n") - (self.repo / "api/agent/sdk/src/index.js").write_text("export const value = 1;\n") - (self.repo / "api/agent/sdk/package.json").write_text( + (self.repo / "api/agent/src/index.js").write_text("export const value = 1;\n") + (self.repo / "api/agent/package.json").write_text( '{"name": "@layerfs/agent", "exports": {".": "./src/index.js", "./package.json": "./package.json"}}\n' ) for name in ("backend", "runtime"): @@ -50,9 +50,9 @@ def setUp(self): (self.repo / f"api/{name}/package.json").write_text( f'{{"name": "@layerfs/{name}", "exports": {{".": "./src/index.js"}}}}\n' ) - (self.repo / "api/agent/cli/src").mkdir(parents=True) - (self.repo / "api/agent/cli/src/layerfs.js").write_text('import "@layerfs/agent";\n') - (self.repo / "api/agent/cli/package.json").write_text('{"name": "@layerfs/cli"}\n') + (self.repo / "api/cli/src").mkdir(parents=True) + (self.repo / "api/cli/src/layerfs.js").write_text('import "@layerfs/agent";\n') + (self.repo / "api/cli/package.json").write_text('{"name": "@layerfs/cli"}\n') git(self.repo, "init", "-q") git(self.repo, "config", "user.name", "Fixture") git(self.repo, "config", "user.email", "fixture@example.invalid") @@ -77,7 +77,7 @@ def test_build_identity_covers_each_product_layer(self): for relative in ( "core/crates/example/src/lib.rs", "engine/crates/example/src/lib.rs", - "api/layerfs-api/src/lib.rs", + "engine/crates/layerfs-api/src/lib.rs", ): path = self.repo / relative path.write_text("pub fn layer() {}\n") @@ -169,7 +169,7 @@ def build_bundle(self, mutate=False): def execute(*a, **kw): if mutate: - (self.repo / "api/agent/sdk/src/index.js").write_text("changed\n") + (self.repo / "api/agent/src/index.js").write_text("changed\n") with patch.object(builds, "execute", side_effect=execute), patch.object(builds, "environment", return_value={}): with contextlib.redirect_stdout(io.StringIO()): @@ -182,16 +182,16 @@ def test_bundle_pins_sdk_and_binary_and_detects_mutation(self): # the bundle mirrors the repository layout under api/ for name in ( "api/package.json", - "api/agent/sdk/src/index.js", + "api/agent/src/index.js", "api/backend/src/index.js", "api/runtime/src/index.js", ): self.assertIn(name, manifest["files"]) - self.assertFalse(any(name.startswith("api/binding/") for name in manifest["files"])) + self.assertFalse(any(name.startswith("engine/crates/layerfs-node/") for name in manifest["files"])) # each package resolves by name through a shim, not a symlink self.assertEqual( (bundle / "api/node_modules/@layerfs/agent/index.js").read_text(), - 'export * from "../../../agent/sdk/src/index.js";\n', + 'export * from "../../../agent/src/index.js";\n', ) self.assertEqual( json.loads((bundle / "api/node_modules/@layerfs/agent/package.json").read_text())["exports"], @@ -202,13 +202,13 @@ def test_bundle_pins_sdk_and_binary_and_detects_mutation(self): 'export * from "../../../backend/src/index.js";\n', ) # the layerfs command, which reaches the agent through its own shim - self.assertIn("api/agent/cli/src/layerfs.js", manifest["files"]) + self.assertIn("api/cli/src/layerfs.js", manifest["files"]) self.assertEqual( - (bundle / "api/agent/cli/node_modules/@layerfs/agent/index.js").read_text(), - 'export * from "../../../../sdk/src/index.js";\n', + (bundle / "api/cli/node_modules/@layerfs/agent/index.js").read_text(), + 'export * from "../../../../agent/src/index.js";\n', ) - (self.repo / "api/agent/sdk/src/index.js").write_text("later edit\n") - self.assertEqual((bundle / "api/agent/sdk/src/index.js").read_text(), "export const value = 1;\n") + (self.repo / "api/agent/src/index.js").write_text("later edit\n") + self.assertEqual((bundle / "api/agent/src/index.js").read_text(), "export const value = 1;\n") file = bundle / "layerfs.node" file.chmod(0o600) file.write_bytes(b"corrupt") diff --git a/tools/worktree_build.py b/tools/worktree_build.py index 9a82672fb..3af7c4bd2 100644 --- a/tools/worktree_build.py +++ b/tools/worktree_build.py @@ -135,27 +135,27 @@ def cargo(args): def copy_sdk(root, bundle): """The JavaScript packages and the `layerfs` command, in the repository's - own layout (#428): api/package.json, api/agent/sdk (@layerfs/agent), - api/backend, api/runtime and api/agent/cli. A bundle holds no symlink, so + own layout: api/package.json, api/agent (@layerfs/agent), + api/backend, api/runtime and api/cli. A bundle holds no symlink, so each package resolves by name through a re-export shim under api/node_modules/@layerfs/ that imports its one real copy.""" destination = bundle / "api" destination.mkdir(parents=True) ignore = shutil.ignore_patterns("node_modules", "__pycache__", "target") - packages = [destination / folder for folder in ("agent/sdk", "backend", "runtime")] + packages = [destination / folder for folder in ("agent", "backend", "runtime")] for package in packages: shutil.copytree(root / "api" / package.relative_to(destination), package, ignore=ignore) shutil.copy2(root / "api/package.json", destination / "package.json") for package in sorted(packages): shim(destination / "node_modules", package) - if (root / "api/agent/cli/package.json").is_file(): - cli = destination / "agent/cli" + if (root / "api/cli/package.json").is_file(): + cli = destination / "cli" cli.mkdir() for folder in ("src", "test"): - if (root / "api/agent/cli" / folder).is_dir(): - shutil.copytree(root / "api/agent/cli" / folder, cli / folder, ignore=ignore) - shutil.copy2(root / "api/agent/cli/package.json", cli / "package.json") - shim(cli / "node_modules", destination / "agent/sdk") + if (root / "api/cli" / folder).is_dir(): + shutil.copytree(root / "api/cli" / folder, cli / folder, ignore=ignore) + shutil.copy2(root / "api/cli/package.json", cli / "package.json") + shim(cli / "node_modules", destination / "agent") def shim(node_modules, package): diff --git a/tools/worktree_resources.py b/tools/worktree_resources.py index 3f53ee5a9..8b1d185a3 100644 --- a/tools/worktree_resources.py +++ b/tools/worktree_resources.py @@ -229,15 +229,13 @@ def inputs(record): "core/crates", "engine/vendor", "engine/crates", - "api/layerfs-api", - "api/agent/sdk", + "api/agent", "api/backend", "api/runtime", - "api/binding", "api/package.json", - "api/agent/cli/src", - "api/agent/cli/test", - "api/agent/cli/package.json", + "api/cli/src", + "api/cli/test", + "api/cli/package.json", ] result = {} for relative in selected: From f406638c80e557b2879a5693a5e213ac291e24be Mon Sep 17 00:00:00 2001 From: YifanXu1999 Date: Tue, 27 Oct 2026 06:18:00 +0800 Subject: [PATCH 10/10] docs(463): record the Rust-out-of-api decision; fix moved links Add the 2026-10-27 owner decision to the #463 implementation record: layerfs-api and the Node binding move to engine/crates and api/ holds only the JavaScript packages (commit b98ac4c2f7), with its LOC and checks. Fix three record links to the binding tests (now engine/crates/layerfs-node/tests) and three migration-spec links to tools/ that the relocation broke. Checks: every local link in core/docs/issues/463 resolves; whitespace. Docs only; Rust/runtime checks do not apply. No tests changed. Production LOC: 102162 -> 102162 (delta 0) Scope: all first-party product implementation (core 38241, engine 61288, api 2633). Docs-only change; tools/production_loc.py counts no docs. Reference absent (retired R9c; last counted 65,417 at tree 498dd1917812). Co-Authored-By: Claude Opus 5.5 --- core/docs/issues/463/IMPLEMENTATION.md | 26 +++++++++++++++++++++++--- core/docs/issues/463/MIGRATION_SPEC.md | 6 +++--- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/core/docs/issues/463/IMPLEMENTATION.md b/core/docs/issues/463/IMPLEMENTATION.md index 6f987e808..23d8146ea 100644 --- a/core/docs/issues/463/IMPLEMENTATION.md +++ b/core/docs/issues/463/IMPLEMENTATION.md @@ -25,9 +25,9 @@ ordinary built addon through Node's exported methods instead. Removed test locations, with all eight behaviors covered at their new homes: - `discovery.rs::tests::a_dropped_guard_releases_the_lock_while_a_forked_child_holds_a_copy` - → [native_discovery.rs](../../../../api/binding/tests/native_discovery.rs). + → [native_discovery.rs](../../../../engine/crates/layerfs-node/tests/native_discovery.rs). - `tests/unit/admission.rs` (two tests: initial admission and deadline Busy) - → [native_admission.rs](../../../../api/binding/tests/native_admission.rs). + → [native_admission.rs](../../../../engine/crates/layerfs-node/tests/native_admission.rs). - `tests/unit/reclaim.rs` (five tests: gone-container cleanup, unrelated 404 custody, replacement-number custody, stopped-container deletion, failed deletion custody) → `native_discovery.rs` above. @@ -36,7 +36,7 @@ The lock regression uses a bounded test-only preload fixture to fork while the actual binding owns the lock. The child retains its open file description while a later exported binding call acquires the released lock. The admission deadline proof pays the full public 60-second wait; no private shorter wait or test-only -product API is introduced. [The test guide](../../../../api/binding/tests/README.md) +product API is introduced. [The test guide](../../../../engine/crates/layerfs-node/tests/README.md) describes the requirements. JavaScript API test targets remain outside CI under the owner's existing exclusion. @@ -196,6 +196,26 @@ parent and staged snapshots. Per-crate totals are identical. Layer subtotals: core 38241; engine 56640; API 7281. No upward guard exception remains. The runtime FP-21 exception remains explicitly separate from the passing checks. +## Follow-up — the Rust leaves `api/` + +On 2026-10-27 the owner rejected the `api/` layout above and directed moving its +Rust out. Commit `b98ac4c2f7` moves `api/layerfs-api` to +`engine/crates/layerfs-api` and `api/binding` to `engine/crates/layerfs-node` +(the addon now builds at `engine/crates/layerfs-node/layerfs.node`), and +flattens the packages: `api/agent/sdk` → `api/agent`, `api/agent/cli` → +`api/cli`, `api/how-to-use` → `api/docs`. `api/` now holds only the published +JavaScript packages. The guard and the LOC counter classify `layerfs-api` and +`layerfs-node` as engine by crate name in both layouts, so the earlier records +above keep their original API subtotals. + +Production LOC: 102162 -> 102162 (delta 0); all 954 files keep their per-file +counts. Under the name-based classification the subtotals are core 38241, +engine 61288, API 2633. Checks: identical Cargo metadata, macOS all-target +check and formatting, the boundary guard, 155 Python tool tests, Ruff, the +JavaScript stand-in tests and a sealed Linux release bundle. dsh ran all ten +scenarios on that bundle; the sandbox scenario's unmount race was a dsh-layerfs +scenario timing issue, fixed there, not a LayerFS change. + ## CI timing record Commit `ef4c26b02b` records the existing Persistence `writer_admission` target's diff --git a/core/docs/issues/463/MIGRATION_SPEC.md b/core/docs/issues/463/MIGRATION_SPEC.md index d3a2e93ff..82c0c385d 100644 --- a/core/docs/issues/463/MIGRATION_SPEC.md +++ b/core/docs/issues/463/MIGRATION_SPEC.md @@ -80,8 +80,8 @@ migration hits most. ## 4. Step 1: layer guard (tooling only) -Files: [core/tools/check_product_boundary.py](../../../tools/check_product_boundary.py) -and [core/tools/test_check_product_boundary.py](../../../tools/test_check_product_boundary.py). +Files: [core/tools/check_product_boundary.py](../../../../tools/check_product_boundary.py) +and [core/tools/test_check_product_boundary.py](../../../../tools/test_check_product_boundary.py). Today the guard has: @@ -206,7 +206,7 @@ For each file, in this order: a test at its new home. Then drop `layerfs-api` from the daemon's dev-dependencies and remove the guard -exception from step 1. Update [core/tools/ci_tests.py](../../../tools/ci_tests.py) +exception from step 1. Update [core/tools/ci_tests.py](../../../../tools/ci_tests.py) for any renamed or moved test target, including its `SLOW` list. Daemon and mount tests are Linux only: build and run them through the worktree's