The pipeline pattern is still very useful, even if it isn't the most important or most well known tenant (I am not sure of this, but maybe you are right). Still, of course it is not perfect. "Everything is a file" has its benefits too, but also is not perfect either.

However, even if not all of {Read,Write,Seek,Truncate,etc} are implemented for all objects, some of them will be implemented, e.g. a TCP socket or character device can use read/write (or some might be read-only or write-only) but is not seekable. This is useful to use programs expecting other files and they will still work. For example, once I had a USB with a exfat file system, which I could not mount, but I knew it contained a ZIP file, so I tried that it it was able to extract the ZIP archive even though it could not be mounted; that is it could treat the USB device itself as a file. And, commonly, it is useful to write stuff that could be written to files, to pipes; for example in Heirloom-mailx you can write attachments to pipes instead of files, and I find this very helpful.

I think that the file system directory tree is not the best way. File descriptors are like capabilities, and that is good (and I agree that it is probably the best way to manage resource permissions), but I think that it could be done better as better capabilities. I think that a single global root and chroot per process are both not the best way; I have a (what I think, at least) better way.

My own design has a file system but does not have directory structures nor file names, but it is a hypertext file system, and files can have multiple forks, and the data streams can contain links (similar to UNIX hard links) to other files. Links can optionally be to a fixed version, or to a changeable version; copy on write can be used if you have both kinds of links to the same file. There is also journaling, and can have locks and transactions that can consist of multiple objects at once (this is necessary in the core system, so that you do not make a mess trying to do such things in user code like SQLite (and any other SQL database engine) does).

My own design also uses "proxy capabilities". Messages can be passed using capabilities, and these messages can contain sequences of bytes and/or capabilities. A program might also create its own capabilities, which can be proxies of others; you can implement fine grained security and also allow fault simulation and many other purposes. All I/O and system calls (except Yield and Quit) must use these capabilities (for full security). A program will receive an initial message when it starts, so it will start up with some capabilities that were passed in that message (which can be whatever capabilities the caller decided to give it). Also, the multiple objects transaction/locking mentioned above is actually a general feature of capabilities and is not specific to disk files; you can make a transaction or lock of any set of objects (if supported; some combinations might not be possible). Proxy capabilities are actually very useful and many of the high-level features of the system are implemented in terms of proxy capabilities, so the kernel does not need to know all of the possible uses.

In this way, you can easily emulate a "chroot per process", although it does not actually work like that. Such an initial message could as easily be used to emulate environment variables or whatever else you might want, too; a POSIX compatibility layer can be possible in user code if needed, although the low-level and high-level design of this system are not designed to be POSIX but rather something different, which does (what I am considering) working better in many ways.

(My own operating system design does not currently have a name.)