The environment is dynamic state, read through $env
Environment variables are ambient authority, not lexical data:
- they flow to child processes;
- they are overlaid by
within [env: …]over a block’s whole dynamic extent; - they are attenuable.
Their single home is context.env_overrides (EnvVars), which rides the dynamic
`Context` subtree through inherit_from / spawn_thread and
serialises across the re-exec boundary (WireContext). ral code reads them as
$env[KEY]; tilde expansion is $env[HOME] and bare command resolution falls
back to $env[PATH] (docs/SPEC.md).
The lexical scope (Env) holds immutable data bindings and does not flow
through inherit_from, so it could never carry the environment to a child —
which is exactly why apply_env reads env_overrides, never scope. The
startup seeding of HOME/USER/PATH/… into Env was therefore a read-side
convenience for a bare $HOME, duplicating keys that within [env: …] only
ever updates in env_overrides; the two views drifted
(env-overrides-scope-overlap).
Resolution: seed the well-known variables into env_overrides only. A bare
$HOME is now an undefined variable; the environment is reached through
$env[KEY] alone. With one authority, a within [env: …] overlay is observed
identically by $env, ~, the child-process environment, and PATH resolution.
This sharpens the dynamic-authority split
rather than straddling it.
Realised in core/src/types/shell/init.rs (seed_default_env_vars).
See also shell-state.