Module-level variables, singletons, or shared mutable state that any code can read or mutate from anywhere. The variable's read and write contracts live in no single place; every consumer relies on its own implicit understanding of when the value is valid, and side effect hides in any call that touches the global without naming it.
A module-level variable mutated from anywhere — the agent reading any single call site cannot bound its impact without paying completeness-check cost across every consumer. The agent reasoning about any read must hold the full mutation timeline in working context window; missing a writer ships an edit that depends on a state assumption the codebase doesn't guarantee.
Access goes through a small named function that owns the read/write contract — and ideally narrows it (read-only, validated). The wrapper enforces the invariant that the global is always valid when read; every consumer of the wrapper inherits the guarantee, and the global's lifecycle becomes inspectable from a single named surface.
All reads and writes go through a named function the agent can grep for, find every consumer of, and reason about as a closed surface. The single audit surface bounds the per-edit reasoning step count; the agent verifies state transitions against the wrapper's contract rather than reconstructing them from scattered call sites.
Smellier version
let currentUser = null;// ...some files later...currentUser = newUser;
Fresher version
function setCurrentUser(user) {currentUser = validate(user);}function getCurrentUser() {return currentUser;}
The blast radius of any change is the whole codebase; behavior depends on hidden write order between callers. Reasoning about state requires tracing every writer — the team's search cost scales with the codebase. Concurrent code becomes a hazard area, and reviewers ship changes that pass single-test verification but break at runtime when global state arrives in a different order.
Behavior depends on hidden write-order between callers the agent discovers one at a time; tracing any bug requires reconstructing a global mutation timeline — high verification-surface cost. The agent generates an edit consistent with the order it discovered and ships it; runtime hits a different order and produces a behavior the agent never reasoned about.
Encapsulating access through a small wrapper adds indirection at every call site; without enforcement, code leaks past the wrapper and the safety promise becomes a leaky abstraction. The wrapper must remain the only access path; every direct read or write that escapes resets the maintenance cost of the smell across the codebase.
Wrapping the global doesn't eliminate the shared-state dependency — every reader still depends on the same value, and the agent still has to model the timeline to reason about reads. The wrapper bounds the visible write surface but not the underlying state; the agent's cache-staleness cost stays the same when the global drifts between sessions.
All access sites become trivially findable; the team can add logging, validation, or a cache without touching consumers. The team's debugging cost drops because the audit surface is one function instead of every file that touches the global, and changes to the read/write contract have a known, bounded blast radius the wrapper documents.
A single named function becomes the audit point; the agent attaches logging, validation, or cache logic in one place instead of chasing every consumer. The agent's per-edit search surface contracts to the wrapper and its callers; retrieval cost on any reasoning about the global drops to the single call to the wrapper.
Wrapping global access without removing the global — adds ceremony while the underlying coupling stays in place. The wrapper looks like encapsulation but leaks every direct mutation back into shared state; reviewers grant the safety presumption without verifying enforcement, multiplying the team's verification cost, and the global's hazards continue with an extra layer of indirection between them and the consumer.
Wrapping globals without narrowing access creates a false safety signal — the wrapper appears to guarantee something it doesn't, and silent leaks become harder to diagnose. The agent reads the wrapper's signature and reasons as if the contract holds; verification-surface cost stays as broad as before, and the agent's downstream edits inherit the violation.