# Compatibility contract ## Baseline The runtime baseline is the exact published `fstream@1.0.12` artifact. The maintained package preserves that object-stream API while correcting bounded readiness, traversal, state-lifetime, replay, and backpressure defects. ## Preserved surface - the exact ordered 16-key CommonJS namespace; - callable/newable Reader and Writer factories and constructor identities; - root aliases through `fstream`, `fstream.js`, `index`, and `index.js`; - all 14 historical deep runtime modules with and without `.js`; - stat metadata and `ready`, `stat`, `entries`, `entry`, recursive `child`, `warn`, `error`, `end`, and `close` event flow; - filters, sorting, pause/resume, disown, abort, piping, size checks, and decorated errors; - opt-in symbolic-link following and hard-link representation; - file, directory, symbolic-link, and hard-link Writers; missing-parent creation; destination replacement; and supported metadata application; - string octal modes, file flags, link paths, and `collect()` staging. ## Intentional corrections ### Readiness Typed Readers begin with `ready === false`. Metadata is available and `ready === true` before the `ready` listener runs, including read-only paths. ### Link traversal `follow: true` propagates to descendants. A target that revisits an ancestor directory remains visible, emits one `warn` with code `ELOOP`, and ends that branch. Separate sibling aliases may each traverse the same target because they are not ancestor cycles. A non-cyclic link may still point outside the lexical source tree. ### Hard-link ownership Hard-link identity belongs to one root traversal. Concurrent and later Readers cannot change one another's File/Link decisions, and the caller's options object does not retain traversal ownership. `Reader.hardLinks` remains present for namespace compatibility but is inert. ### Terminal lifecycle Writer completion waits for its applicable stat, mode, ownership, timestamp, and created-parent work. A successful `close` is terminal and idempotent; no filesystem metadata operation starts afterward. Legitimate errors detected before close remain observable. ### Backpressure and replay ProxyWriter corrects the upstream `_needDrain` flag defect and respects its selected delegate's backpressure. Destinationless `collect().pipe()` removes its collector before replay, so it preserves entry/data/end order and terminates instead of collecting its own replayed entries. ### Runtime dependency tree Deprecated Buffer construction is removed. Native filesystem helpers replace the old `inherits`, `mkdirp`, and `rimraf` production paths. Those new helpers are private, not supported deep imports. ## Additive packaging - a real ESM default export identical to the CommonJS namespace; - named ESM root exports and default ESM deep-module facades; - TypeScript 3.9-compatible CommonJS and modern ESM declarations; - explicit conditional exports for roots and historical deep entries. These additions do not create a browser contract. Imports read Node filesystem state and streams remain stateful; no `sideEffects: false` claim is made. ## Runtime boundary Node.js 14.15.1 or newer is supported. Development tooling may require a newer Node version but is absent from production installs. Browser runtimes and Node versions below the declared floor are outside the contract. Filesystem capabilities vary across platforms, mounts, ownership, and privilege. Symlinks, hard links, `chown`, link metadata, timestamps, and Windows path behavior cannot be identical when the host lacks a capability. ## Non-contractual details Private helper layout, development dependencies, fixtures, exact stack trace formatting, and the obsolete upstream dependency topology are not public API. The package does not provide filesystem transactions, path containment, archive validation, or a browser filesystem abstraction.