Conformance policy

Rush is a POSIX-facing shell with Bash compatibility and interactive UX improvements. That means compatibility decisions have to balance three reference points: the POSIX shell language, real /bin/sh implementations, and the habits users bring from Bash.

This page explains how Rush chooses behavior when those reference points disagree. Concrete known differences are recorded in the compatibility notes.

Modes

Rush treats modes as different contracts, not as cosmetic flags.

The POSIX mode policy is strict because it has the clearest external standard. Default mode starts from the same model, then adds compatibility features carefully.

POSIX mode

rush --posix targets POSIX.1-2024 / Issue 8. POSIX mode is not a promise that every historical shell does the same thing; it is a promise that Rush uses the specification as the first authority.

When POSIX specifies behavior, the specification wins

If POSIX defines the grammar, expansion, redirection, command execution, special builtin behavior, variable assignment semantics, diagnostic requirement, or exit status for a case, Rush follows POSIX in POSIX mode.

Common shell behavior is useful evidence when reading the standard, but it is not a veto. If Bash, dash, or another shell diverges from POSIX, Rush should not copy that divergence in POSIX mode unless the project deliberately documents a compatibility exception.

When POSIX leaves a gap, classify it first

Before choosing behavior from existing shells, Rush should identify what kind of freedom POSIX leaves:

This classification matters because undefined behavior does not deserve the same compatibility weight as implementation-defined behavior.

For unspecified or implementation-defined behavior, survey trusted shells

When POSIX leaves room for more than one valid behavior, Rush surveys established shells before choosing. The primary survey set is:

When those shells agree, Rush normally follows them. When they disagree, Rush may also consult platform shells such as FreeBSD /bin/sh, macOS /bin/sh, and BusyBox ash, plus yash, ksh93, current Bash default mode, or macOS Bash 3.2 depending on the feature and migration risk.

FreeBSD /bin/sh and macOS /bin/sh are important platform references, but they are not required for every local conformance run. They should be exercised when available locally, in platform CI, or when a compatibility decision specifically affects those systems.

macOS Bash 3.2 is tracked as a platform and legacy compatibility reference, not as the main Bash compatibility target. When current stable Bash and macOS Bash 3.2 disagree, Rush normally follows current stable Bash unless the decision is specifically about macOS compatibility or existing macOS scripts.

Default Bash behavior is important for compatibility, but it is not the primary oracle for POSIX mode. Bash extensions that are useful in normal Rush or interactive Rush can still be rejected by rush --posix.

When shells disagree, use stable tie-breakers

If POSIX leaves room and surveyed shells disagree, Rush prefers the behavior that is:

  1. most consistent with the POSIX execution model;
  2. most portable across real scripts and common /bin/sh implementations;
  3. least surprising to users who understand shell semantics;
  4. safest when state, files, jobs, traps, or redirections are involved;
  5. easiest to diagnose clearly when the script is non-portable or invalid.

User-friendly behavior is the final tie-breaker, not the first rule. In POSIX mode, friendly behavior means helping users write portable and predictable scripts, even when that means rejecting a familiar Bashism.

For undefined behavior, prefer diagnostics and safety

When a script relies on undefined POSIX behavior, Rush is not obligated to mimic any existing shell. In POSIX mode, Rush should prefer clear diagnostics, safe outcomes, and predictable state over silently accepting non-portable constructs.

Rush may still accept undefined or extension behavior for practical compatibility, but that choice should be intentional, tested, and documented. Accepting it in default or interactive Rush does not imply that rush --posix should accept it too.

Default mode

Default Rush is POSIX-facing with selected compatibility extensions. It is the mode for normal non-interactive execution when --posix is not requested. Its job is to preserve POSIX script meaning while accepting common extensions that make Rush practical for Bash-shaped workflows.

Valid POSIX scripts keep POSIX meaning

If a script is valid POSIX, default Rush should normally behave the same as rush --posix. Default mode may accept additional syntax or features, but extensions should not casually change the meaning of portable scripts.

This preserves Rush's goal of being useful as a /bin/sh replacement while still allowing normal Rush to be more convenient than strict POSIX mode.

Extensions should be common, useful, and mostly additive

Default mode may accept non-POSIX features when they are common in Bash scripts, common across Bourne-family shells, important for interactive use, or useful for migration. Rush prefers additive extensions: syntax or behavior that POSIX does not define, rather than changes to the meaning of valid POSIX scripts.

When an extension conflicts with POSIX semantics, Rush requires a stronger reason to enable it by default. The project should weigh migration value, surprise, safety, and whether the behavior can be isolated to clearly non-POSIX syntax.

Bash is the main extension reference

For Bash extensions, current stable GNU Bash default mode is the primary behavior reference. macOS Bash 3.2 is an important migration signal, but not the sole target. When Bash versions disagree, Rush normally prefers current stable Bash unless older behavior is still common in real scripts or important on supported platforms.

For extensions that also exist in other shell families, Rush may survey ksh93, mksh, zsh, BusyBox ash, dash, or FreeBSD sh depending on the feature. The goal is practical compatibility, not bug-for-bug emulation of any one shell.

Bash compatibility

Bash compatibility is a migration goal, not a replacement for the POSIX conformance policy. Rush should support Bash behavior when it unlocks real scripts, preserves familiar interactive use, or reduces migration cost without undermining the POSIX-facing core.

Rush should not chase bug-for-bug Bash emulation by default. If a Bash behavior is undocumented, surprising, unsafe, or inconsistent across Bash versions, Rush can choose a clearer behavior and record the difference.

Recording decisions

Compatibility decisions should become tests whenever practical. A decision is strongest when it includes:

The compatibility notes are the user-facing place for concrete differences. This policy explains how those differences should be chosen.