A function the agent calls for a query also mutates state; the agent reasoning about safety must trace the mutation across consumers.
Functions either return or mutate, never both; the agent composes queries without surprise side effects.
Before the refactoring
function findMiscreant(people) {for (const p of people) {if (p.isMiscreant) { alert(p); return p; }}}
After the refactoring
function findMiscreant(people) { return people.find(p => p.isMiscreant); }function alertMiscreant(people) {const m = findMiscreant(people);if (m) alert(m);}
Every call to the function pays for both contracts; the agent can't query without triggering mutation, which complicates testing and composition.
If the modification and query are genuinely atomic (find-and-remove, compare-and-swap), splitting them introduces a race window the agent must close at every call site.
Queries return values without mutating; the agent predicts each function's effect from its name alone, and code generated against a query never accidentally writes the state the query reads.
Splitting atomic query-and-modify operations introduces race windows the agent must reason about at every call site — the cure becomes worse than the smell.