## ADDED Requirements ### Requirement: Filesystem API matching node:fs/promises The system SHALL provide `sandbox.fs` implementing the Node.js `fs/promises` API: - `readFile(path, encoding?)` → `Buffer | string` - `writeFile(path, data)` → `void` - `appendFile(path, data)` → `void` - `mkdir(path, { recursive? })` → `void` - `readdir(path, { withFileTypes? })` → `string[] | Dirent[]` - `stat(path)` / `lstat(path)` → `Stats` - `unlink(path)`, `rm(path, { recursive?, force? })`, `rmdir(path)` → `void` - `rename(oldPath, newPath)` → `void` - `copyFile(src, dest)` → `void` - `chmod(path, mode)`, `chown(path, uid, gid)` → `void` - `symlink(target, path)`, `readlink(path)` → `void` - `realpath(path)`, `truncate(path, len?)` → `void` - `mkdtemp(prefix)` → `string` - `access(path)`, `exists(path)` → `boolean` #### Scenario: ReadFile returns correct content - **WHEN** `sandbox.fs.readFile("/etc/hostname", "utf8")` is called - **THEN** it SHALL return the file content as a string #### Scenario: WriteFile creates new file - **WHEN** `sandbox.fs.writeFile("/tmp/test.txt", "hello")` is called - **THEN** subsequent `sandbox.fs.readFile("/tmp/test.txt", "utf8")` SHALL return `"hello"` #### Scenario: Readdir lists directory contents - **WHEN** `sandbox.fs.readdir("/")` is called - **THEN** it SHALL return an array of filenames #### Scenario: Stat returns file metadata - **WHEN** `sandbox.fs.stat("/etc/hostname")` is called - **THEN** it SHALL return a `Stats`-compatible object with `size`, `isFile()`, `isDirectory()`, `mode`, `uid`, `gid`, `mtime`, etc. #### Scenario: Mkdir creates intermediate directories - **WHEN** `sandbox.fs.mkdir("/tmp/a/b/c", { recursive: true })` is called - **THEN** the directory `/tmp/a/b/c` SHALL exist #### Scenario: Exists returns false for missing files - **WHEN** `sandbox.fs.exists("/nonexistent")` is called - **THEN** it SHALL return `false`