Design an in-memory file system that supports four operations:
- `ls(path)`: If `path` is a file path, return a list containing only the file name. If `path` is a directory path, return the lexicographically sorted list of file and sub-directory names directly inside the directory.
- `mkdir(path)`: Create a new directory at `path`. If middle directories in the path don't exist, they should be created too.
- `addContentToFile(path, content)`: If the file at `path` doesn't exist, create it (along with any necessary parent dirs). If it does, append content to its existing content.
- `readContentFromFile(path)`: Return the content of the file at `path`.
All paths are absolute (start with `/`) and use `/` as separator. Path components are non-empty, lowercase letters and digits only.
**For the auto-grader:** implement `fileSystemOps(operations)` returning the result of each operation in order. Each op is one of:
- `["ls", path]` → string[]
- `["mkdir", path]` → `null` / `None`
- `["addContentToFile", path, content]` → `null` / `None`
- `["readContentFromFile", path]` → string