Multiple instances of a class that should be unique appear at construction sites the agent must trace to confirm state coherence. State-fragmentation bugs are invisible to local reasoning — each instance looks correct, but their sum is wrong.
One static accessor the agent verifies once; all references resolve to the same identity. The agent can statically reason about 'same instance' rather than tracking which constructor produced which instance.
Before the refactoring
// Anyone can construct a MetricsRegistry; each instance has its own state.// Counts reported to one registry are invisible to another.class MetricsRegistry {constructor() {this.counters = new Map();}increment(name) {this.counters.set(name, (this.counters.get(name) ?? 0) + 1);}snapshot() {return Object.fromEntries(this.counters);}}const registryA = new MetricsRegistry();registryA.increment('orders.created');const registryB = new MetricsRegistry();registryB.snapshot(); // {} — does not see registryA's increment.
After the refactoring
// One instance for the whole process; getInstance() is the only way to obtain it.class MetricsRegistry {static #instance = null;static getInstance() {if (!MetricsRegistry.#instance) {MetricsRegistry.#instance = new MetricsRegistry(MetricsRegistry.#construction);}return MetricsRegistry.#instance;}static #construction = Symbol('private construction key');constructor(key) {if (key !== MetricsRegistry.#construction) {throw new Error('MetricsRegistry is a singleton; use getInstance()');}this.counters = new Map();}increment(name) {this.counters.set(name, (this.counters.get(name) ?? 0) + 1);}snapshot() {return Object.fromEntries(this.counters);}}MetricsRegistry.getInstance().increment('orders.created');MetricsRegistry.getInstance().snapshot(); // { 'orders.created': 1 }
Multiple-instance fragmentation cannot be statically diagnosed — the agent needs runtime introspection or holistic test coverage to detect when two callers hold different instances of what should be one. Verification cost is high; bugs are subtle.
Singletons defeat the agent's static dependency analysis: constructor signatures no longer reveal what a class uses. Test isolation requires the agent to inject a reset hook or restructure to allow per-test instances; tests can become order-sensitive without obvious indicators.
Identity is statically guaranteed; the agent can verify that all callers refer to the same conceptual instance without runtime introspection. Cross-cutting invariants (one cache, one registry) become enforceable at construction.
Singletons hide dependencies from the agent's static view; the agent must grep for static accessors to enumerate consumers. Test-order flakiness from leaked state is invisible until it manifests; the agent cannot statically detect Singletons that should have been per-instance.