Once Is Too Few, Twice Is Noise

A memory that the harness delivers, instead of waiting to be asked for, has two limits. Repeat it and it stops telling the agent anything. Deliver it once and that single delivery has to be in front of the agent when it makes the decision the note is about. The usual fix for the first limit quietly breaks the second.

A memory that the harness delivers to an agent, rather than waiting for the agent to look it up, has to satisfy two constraints that most designs treat as one.

The first is a budget. Show the same content too often and it stops being read. Every field that sends alerts to busy people has learned this, usually after an incident. The budget belongs to the reader: it is the number of times the same thing can appear before it turns into background.

Then there is a deadline, which has nothing to do with the reader's patience and everything to do with when the decision happens. A delivered note has to be in front of the agent at the moment it chooses the action the note is about. If it arrived earlier and is gone by then, it did nothing, however cleanly it was delivered.

The standard fix for the budget is a cooldown: deliver each note once, then hold it back for a while. That fixes the budget and leaves the deadline resting on a single shot. In vectr, an open-source code-search and agent-memory tool I maintain, that shot was lost three different ways: on a request that could not carry it, inside a single model call that nothing after it could see, and several turns ahead of the edit it was written for. The tool's own log recorded a delivery every time.

One piece of plumbing explains most of what follows. An agent works in a loop of model calls, and what the model can see on any one call is its context. Each call is a fresh request to the model API, and the agent client builds it from the conversation history it keeps on its own side. A memory can reach the model in one of two places: written into that history, where later requests carry it too, or attached to one outgoing request on its way to the model, where nothing after that request will see it.

Part 01
The Budget
01

Repetition Has a Cost Curve: Habituation, Alarm Fatigue, Wear-Out

Biology has a name for the budget. Habituation, in the wording of Rankin and colleagues' 2009 revision of the field's standard description, is "a behavioral response decrement that results from repeated stimulation and that does not involve sensory adaptation/sensory fatigue or motor fatigue." The exclusions carry the meaning. The sense organ still works and the muscle is not tired. The animal has learned that this stimulus, here, predicts nothing, which is why the paper can note that habituation is "termed 'the simplest form of learning'".

The defining characteristics were first listed by Thompson and Spencer in 1966, and three of them, as the 2009 revision states them, read like notes for anyone designing a notification. Repetition produces "a progressive decrease in some parameter of a response to an asymptotic level." If the stimulus is withheld, "the response recovers at least partially", which the field calls spontaneous recovery. And after several rounds of repetition and recovery, "the response decrement becomes successively more rapid and/or more pronounced." A fourth adds that "more frequent stimulation results in more rapid and/or more pronounced response decrement, and more rapid spontaneous recovery."

Translated into notification design, frequency drains the budget, a pause refills it only partly, and a message that has been through several rounds of repeat, pause and repeat wears out faster each round. All of that was established in animals, not models. I still find the third characteristic a useful warning against any cooldown that waits an hour and then sends the identical text again.

Alarm fatigue in hospitals

Hospitals met the same curve at the bedside. Sendelbach and Funk's 2013 article states the range plainly: "Research has demonstrated that 72% to 99% of clinical alarms are false." The same year the Joint Commission, which accredits US hospitals, issued a Sentinel Event Alert on alarm safety estimating that "between 85 and 99 percent of alarm signals do not require clinical intervention." The alert describes what follows: clinicians "become desensitized or immune to the sounds, and are overwhelmed by information," and may "turn down the volume of the alarm setting, turn it off, or adjust the alarm settings outside the limits that are safe." Its database held 98 alarm-related events between January 2009 and June 2012, 80 of which ended in death. Reporting to that database is voluntary, so the count shows that such events happen, not how often.

Notice what the alert describes. Nobody stops hearing the alarm; people hear it and turn it down or off, and that setting is still in place when the true alarm comes.

Alert fatigue in security operations

A SOC has the same problem under the name alert fatigue. Tariq and colleagues' 2025 survey in ACM Computing Surveys starts from the observation that industry and academia have both highlighted alert fatigue and burnout among SOC analysts, and reviews the proposed remedies through three lenses: automation, augmentation and human-AI collaboration. One remedy sets the unit of the budget, and a 2026 preprint survey of AI-driven alert screening describes it. Alert correlation is "the automated grouping of semantically and temporally related alerts into coherent incident hypotheses", which the authors call "a potent alert volume reducer (collapsing hundreds of related alerts into a single enriched incident)." The analyst's attention is spent per incident, not per alert. Two sensors reporting the same intrusion should cost one look.

Wear-out in advertising and banner blindness on the web

Persuasion research measured the curve directly. In Cacioppo and Petty's first experiment, people heard a persuasive message zero, one, three or five times in succession; in the second, one, three or five times. In both, "agreement first increased, then decreased as exposure frequency increased (regardless of the position advocated)." The second experiment also recorded what listeners were thinking: counterarguments first fell and then rose, and thoughts unrelated to the topic increased with exposure. Past a few repetitions, the same listeners argued with the message more and wandered off it further. Advertising research calls the rising and falling halves of that curve wear-in and wear-out, the terms around which Pechmann and Stewart's 1988 review organised the field's findings.

Web design found a version in which louder made it worse. Benway's 1998 study gave people specific items to find on a page and found that they often overlooked distinctive banners. In the paper's words, "the user who really wants to find the information the designer has highlighted is not likely to do so." Users "saw banners hardly at all when clicking a banner was not required to accomplish a task."

What a signal tells its reader

In each of these, the signal keeps arriving and the reader stops treating it as news. If the signal is not news, that is the right response. A signal informs its reader to the extent that its appearing depends on the state of the world. An alarm that sounds whether or not the patient is in trouble says nothing about the patient, and a nurse who learns to discount it has learned something true.

Analogy: the smoke detector over the toaster

A smoke detector fitted right above a toaster goes off every morning. It is not broken. It detects smoke perfectly, including the harmless smoke of breakfast. Within a week the household fans it with a tea towel without looking up. Within a month somebody takes the battery out. The detector has not stopped working; it has stopped meaning anything, because it fires on mornings with a fire and mornings without one alike.

The analogy breaks in one place that matters for agents. A model cannot take the battery out. A reminder attached to every tool result stays in the context, word for word, every time. Whatever goes wrong goes wrong in how much weight the text gets, not in whether it arrives.

How much a reminder tells you, in bits

Let S be the state: either the situation needs the action (probability q, the base rate) or it does not. Let M be whether the reminder fires. It fires with probability a when the action is needed and b when it is not. The mutual information between them is

I(M;S) = H(M) - H(M|S) = h(q·a + (1-q)·b) - [ q·h(a) + (1-q)·h(b) ] h(p) = -p·log2(p) - (1-p)·log2(1-p)

where h is the binary entropy. If a = b, the firing does not depend on the state, the two terms are equal, and I = 0. A footer that fires on every response is the limiting case: a = b = 1, so H(M) = 0 and there is nothing to learn from seeing it. The same collapse shows up in the reminder's precision, the share of firings that were needed:

P(needed | fired) = q·a / (q·a + (1-q)·b)

With a = b this is exactly q. Seeing the reminder leaves the reader where the base rate already had them.

Content and presence are two separate signals

A repeated reminder can carry information in two ways. Its content can tell the reader something new, and identical text does that once: by the second reading there is nothing left in it. Its presence can tell the reader something about the current state, but only if whether it appears depends on that state. An always-on footer loses both after the first read. A reminder gated on state keeps the second indefinitely, even though its words never change.

Interactive · Demo 1
How Much Does a Reminder Tell the Agent?

Set how often a situation actually calls for the reminder, and how the reminder decides to fire. Watch how often it is right when it fires, and how many bits its appearing carries about the situation. Then move the two firing rates together and see the information go to zero, however reliable the reminder looks.

10%
100%
100%
Per 100 turns. "Information" is I(M;S) in bits per turn; "of the maximum" divides it by H(S), the most any signal about this state could carry. It measures what the reminder's presence says about the state, not whether a reader attends to it.

When repetition is the fix

Repetition is not always the mistake. A long agent session has the opposite problem too: an instruction given once at the start loses its hold as the context grows. Bui's 2026 account of building a terminal coding agent describes counteracting "instruction fade-out through event-driven system reminders." Wu and colleagues give the failure a name, behavioral state decay, in which decision-relevant facts are "buried in the context window or pushed beyond it, failing to influence decisions when needed."

Repeating a note can therefore help or hurt, depending on why it is repeated. Both papers resolve the tension the same way, by making the repeat depend on an event rather than on the clock or on every response. That handles the budget. It does not say which turn a rarely firing note should fire on, and that choice turned out to be where things broke.

Part 02
The Deadline
03

The Cooldown Fix for Agent Memory, and the One Shot It Leaves

The general form of the footer fix, for stored notes, is a cooldown. When a note is delivered, record that; for some window afterwards, do not deliver it again.

vectr delivers stored notes through two paths. Hooks run at fixed points in the session and hand their output to the agent client. The proxy sits on the wire instead: a local process between the agent client and the model API that reads each outgoing request, matches stored notes against what the agent is currently doing, and appends a short context block to the request when one matches. The losses described below all happened on the proxy path.

On the proxy, the cooldown is a bounded ring. The last 30 delivered notes are suppressed (cooldown_items: 30). Since version 1.11.0 a time limit sits on top: a suppression lapses once the note's most recent delivery is more than an hour old (cooldown_ttl_seconds: 3600), and each new delivery restarts the clock.

Whose budget is it?

Getting the cooldown's key right took two attempts, and both mistakes were about the unit of the budget. A budget belongs to a reader, so the ledger has to be keyed on something that identifies the reader. vectr first keyed it on a hash of the conversation's first user message. Every new first message minted a fresh ledger, and, as the 1.6.0 changelog puts it, "a note could be re-injected seconds after its last emission." The fix keyed the cooldown on the proxy process, since one proxy serves one editor session. A process can run for days, though, and with no time limit "under a process-scoped session key a suppression could never expire," in the 1.11.0 changelog's words. Key the budget too narrowly and the same reader sees repeats. Key it broadly with no decay and the note never comes back.

From many chances to one

A cooldown fixes the budget and changes the problem. Without one, a note that matches on every relevant request is delivered on every relevant request, so whichever request turns out to be the decision, the note is on it. With a deliver-once cooldown, the note is present at the decision only if the request it was delivered on is the decision, or if the delivery is still visible by then. On the proxy path a delivery is visible for exactly one request, which leaves the first condition.

The cooldown converts a repetition problem into a timing problem

Before the cooldown, the risk was too many copies. After it, the risk is one copy in the wrong place. The cooldown itself is fine. What it does is put the entire outcome on the choice of request for the single delivery.

04

Three Ways an Agent Memory Delivery Was Lost

Lost 1: spent on a request that could not carry it

The proxy appends a block only when the request's last message comes from the user. That restriction looks fussy and is load-bearing. The code's own explanation gives three reasons, checked against real request shapes. The first request from the agent client used in these runs ends with an 8.7 KB system message that carries the last prompt-cache breakpoint, so appending to the earlier user message would change the cached prefix and throw the cache away. Appending inside the system message would give a recalled note the authority of a system instruction. Inventing a new user message would fabricate a turn the user never sent. So a request that cannot take an appended block is supposed to be skipped, and the note delivered on the next one that can.

That is not what happened. On the first request, which ended with the system message, the note matching ran anyway. The note was retrieved, the audit log wrote its injection line, and the cooldown was charged. On the following requests, the ones that could carry it, the cooldown suppressed it. In the injection benchmark's words, "The note gets exactly one shot, and it is spent on the one request that structurally cannot receive it."

Across three scenarios and one controlled reproduction, zero of four planned deliveries reached the model. A diagnostic proxy chained in front of vectr's captured the request shapes: the first request ended with ['user','system'] and could not be appended to; the second, third and fourth could; and a file path first appeared in the third, from a read, and again in the fourth, from a read and an edit. The reproduction's proxy counters read 'requests':5, 'injected':0, 'inject_skipped':4, alongside exactly one injection line in the audit log of the daemon. The capture does not show why the note matched a request with no file path in it. The benchmark pins the loss on request 1 by elimination: requests 2 and 3 could take a block, so a retrieval on either would have produced an append, and the proxy counted none. The provider was ruled out as well. It answered in 2.7-34.7 ms against a 600 ms timeout and returned content every time.

The audit log said the note was injected. Only a second counter, kept by the proxy itself and counting blocks actually appended, said otherwise.

The fix, in version 1.6.0, has three parts. The proxy now checks whether a request can carry a block before running retrieval at all, so a request that cannot costs nothing. The cooldown is charged only when delivery is confirmed: the proxy gets an opaque token back with the selection, confirms past a successful append, and the confirmation rides along on the next call to the daemon, so no extra round trip is added. And the audit was split. PROACTIVE_RETRIEVE is written when a note is selected, PROACTIVE_INJECT only when delivery is confirmed, "so the injection count is an honest lower bound on what reached the model."

The commit also documents what the fix leaves. A caller that delivers and then dies never returns its token, which is why the injection count is a lower bound rather than an exact count. Two requests in flight at once can both select the same note before either confirms, "which is duplicate injection rather than a lost note." In the terms used here, that residual is a budget-versus-deadline trade: where the design errs, it errs toward a second copy rather than none.

Lost 2: visible for one model call

With delivery fixed, every injection-enabled cell in the next round confirmed a delivered note, and behaviour still did not change. Each scenario was a trap that the agent falls into unless the note steers it away. In the baseline arm, agents with the note avoided the trap 0 times in 7, the same as the controls that had no note. Four further arms changed the wording and content of the block, and each scored 0 of 2.

One cause had nothing to do with timing: the proxy sent only the note's title, and the body, where the actual guidance lived, never crossed the wire. Version 1.7.0 fixed that. Content alone was not the whole story, though. Three of the four arms sent the full body under the old timing, and each still scored 0 of 2.

The second cause came from the shape of the proxy itself. The block "rides one outbound request, is never echoed into the editor's local conversation state, and the cooldown then suppresses re-injection." The agent client keeps the conversation and builds each request from it. The proxy sees requests on their way out and responses on their way back; the conversation record stays on the client's side, and the proxy does not write into it. So the next request is built without the block. A delivered note was in the model's context for one call: one step of reasoning, in a task that takes dozens.

Lost 3: delivered before the decision

A note about a file is naturally triggered when the agent touches that file, and an agent's first touch is a read. Reading comes early. Editing comes later, often several turns later, after more exploration. So the note arrived at the first read, was visible for that one call, went into cooldown, and was gone when the edit it was meant to shape was being written.

The benchmark measured the result of that sequence: "in 6 of 7 baseline cells the note was out of context before the first mutating edit." That figure is the combined effect of Lost 2 and Lost 3. A delivery that lasts one call, a trigger that fires at the first read and a cooldown that retires the note after one delivery together put the note in the wrong place.

The proxy cannot know in advance which request is the decision. The edit appears only in the history of the request after the one where it was chosen, so by the time the evidence arrives, the moment has passed. The fix works with that constraint instead of guessing: it changed what ends a note's eligibility. Since 1.7.0, a note whose declared anchor is a file stays eligible for re-delivery while the file is only being read, and "retires the first time a request's window shows the file actually edited." The changelog describes the old behaviour as "too early, then evicted." In the code, a selected note whose anchor file has not been edited is left out of the cooldown write-back entirely, so it is selected again on the next request that matches. It rides along on every request until the edit shows up, including the request that carries the edit itself, and only then retires.

The cooldown ends on the action the note is about, not on its delivery. Two limits come with it. The rule covers only notes anchored to that file; other kinds of match keep the fixed cooldown. And an edit is recognised from the edit-type tool calls in the request's own history, so a file changed through a shell command does not count, and the note keeps riding requests until something else takes it out of the matching window.

Re-delivering on every request sounds like it should break the budget, and on a channel that writes into the history it would: each delivery would add another copy. On the proxy it does not, because the previous copy was never written into the history, so every request carries exactly one. The copy is not free. The block is appended after the last cache breakpoint, so each request pays for it at the uncached input rate, where a copy sitting in the history would usually be read from the cache.

Interactive · Demo 2
Follow One Note Through a Session

Each switch is one of the three fixes. Flip them one at a time and watch two things on the gold row, the request whose reply is the edit: whether the note is in the model's context there, and how many copies of it are. Then switch the channel to one that writes into the history and see the same retirement rule turn into a budget problem.

#RequestCan carryWhat happens to the noteCopies in context
An illustrative session, not a captured transcript. The note is anchored to app/settings.py and matches on every request shown; the cooldown window outlasts the session. "Note-copies billed" sums the copies carried by each request, before any prompt-cache discount, so it overstates the history channel's cost: a copy kept in the history usually sits in the cached prefix and is cheaper to resend than a fresh append after the last breakpoint.
All three losses were logged as deliveries

In the first, the audit log wrote an injection line for a block that was never appended. In the second and third, the block really was appended, and the log was right that it was sent. In none of them did "sent" mean "in front of the model when the edit was chosen." The instrument that caught the first loss was a counter of appended blocks. The one that caught the other two was a check of whether the note was still in context at the agent's first edit.

Part 03
The Policy
05

Budget and Deadline Are Separate Controls in a Memory Delivery Policy

Stated generally, a delivery policy has to set two things, and they are keyed to different events. Treating them as one setting is how a fix for one breaks the other.

The budget is keyed to the reader

How many times may the same content appear before it is discounted? The answer is small, and the unit that matters is the underlying condition, not the channel, for the same reason a SOC correlates alerts into incidents. If one note matches both the agent's prompt and its next tool call, it should appear once in that turn, not twice through two channels.

vectr's hook surfaces share a per-turn ledger for exactly this. It is keyed on the note's identity, reset at every user prompt, and shared by the session-start, before-tool-call and prompt-time paths; the 1.5.0 changelog describes it as keeping "any note from firing twice in the same turn." The proxy looks up the same ledger, but under its own per-process session id, which by design never matches the session id the agent client supplies to the hooks. The code calls that a guaranteed lookup miss. So today the proxy and a hook can each deliver the same note in the same turn. The code comment notes that the lookup itself would start deduplicating as soon as the two identities are unified; unifying them is the open work.

The deadline is keyed to the decision

When is the note needed? At the moment the action it concerns is chosen. A delivery is therefore not complete when the text is sent; it is complete when the action it informs has happened. Retirement should follow that action: the edit to the anchored file, which vectr's proxy does now, or the run of the anchored command, which it does not.

The retirement rule also has to match the channel. On a channel whose deliveries stay in the history, one delivery persists, so delivering once and then holding back is enough for as long as the history keeps it, and re-delivering stacks copies. On a channel that appends to a single request, a delivery vanishes after one call, so the note has to be re-sent on every request until the action, and re-sending stacks nothing. The same "deliver once" rule is correct on the first channel and useless on the second.

Distinct actions renew eligibility; repeated matches do not

A note anchored to a command is relevant at every distinct run of that command, because each run is a new decision. A note that says the deploy script needs a flag is as relevant to the fourth deploy as to the first. What should be suppressed is the burst: an agent retrying the same failing command five times in a row is making one decision, and a short debounce covers it. A note matched by semantic similarity to the conversation is different. A second match on the same topic carries no new decision, and a long cooldown fits it.

That is a recommendation, and vectr's hook channel currently does close to the reverse. A deterministic trigger, one anchored to a file path or a command, fires once and is then suppressed for the rest of the session, until a compaction resets the ledger; the code describes that suppression as the deterministic triggers' "debounce". A semantic match becomes eligible again after ten user turns (cooldown_turns: 10). Individual triggers can also declare their own time-based cooldown, but only if their author opts in. Part of the asymmetry is history. The once-per-session ledger came first, and when the ten-turn semantic cooldown was added, the configuration comment says the deterministic triggers "keep the pre-existing per-session-per-axis fire ledger as their debounce." Whether a hook's output stays in the history is decided by the agent client, not by the memory tool. If it does stay until compaction, once per session is defensible, and resetting at compaction restores eligibility at the right moment. For a command note it still means the reminder rides along with the first run and is, at best, far back in the context by the fourth, which is the decay problem from Part 1. Per-invocation eligibility on a history-keeping channel would need a check that the last copy has left the recent part of the context before sending another, so the budget is not spent twice on the same decision.

Measure at the decision, not at the send

All three losses passed as deliveries in the system's own records. The measurements that caught them were a proxy counter of blocks actually appended and a check of whether the note was still in context at the first edit. A delivery metric that stops at "selected" or "sent" reports the budget as spent and hides that the deadline was missed. A fuller treatment of stage-by-stage measurement, including what happens when the instruments themselves are wrong, is in Agent Memory Fails in Three Places and Gets Measured as One.

ControlKeyed toShould end onWhat vectr ships
Per-turn dedupThe reader, per conditionThe next user promptA ledger keyed on note id, shared by the hook surfaces; the proxy's lookup never matches
Cross-turn cooldownThe readerA count or time limitProxy: last 30 notes plus a 1-hour limit, refreshed on re-delivery. Hooks: once per session per trigger until compaction; semantic matches after 10 turns
RetirementThe decisionThe action the note is aboutProxy, file-anchored notes: retire when a request shows the file edited. Commands: not implemented
Delivery gateThe requestConfirmed appendProxy checks appendability before retrieval and charges on confirmed delivery
The first two rows protect the budget, the last two the deadline. Each row has a different event that ends it.
06

What Timing Cannot Fix: Delivered, On Time, and Not Believed

With the full body sent, retirement tied to the edit, and a framing whose skepticism scales with who wrote the note (an automatic capture, the agent, or a person), the same benchmark was run again on three scenarios, one run each. All three cells were valid, meaning the note was confirmed delivered. In two of them the agent avoided the trap the note warned about. In the third it walked into it. Three cells is too small a sample to generalise from, and because the three fixes landed together, the result cannot be credited to any single one of them.

The failing scenario planted a note saying the test suite contained a randomly failing test and naming a deterministic subset to run instead. The agent received the note on the right turn and ran the full, flaky suite anyway. An earlier round recorded why a model might do that. In a cell where the note was on the decision turn, in full and without the skeptical framing, "the executor model still declined to act on it, explicitly citing that the claim did not come from the user and had no corroboration in the repo."

The two scenarios where the note worked had something in common: the agent could confirm the claim by reading a second file. In the one that failed, the note was the only source for a claim about a nondeterministic outcome. Two of the scenarios were also run through the hooks instead of the proxy, and gave the same split: the note worked where it could be checked and not where it could not. In the hook-delivered flaky-test run the split went further, inside a single note. The agent applied the code fix the note described and declined the note's advice on which tests to run. The benchmark's summary of the comparison between channels is "channel parity, not channel authority."

It is hard to call the model wrong. A note that says "this test is flaky, don't trust its failures, run this subset instead" is word for word what a prompt injection trying to hide a real regression would say. Treating uncorroborated text that appears in its context, without the user having said it, with suspicion is a reasonable default for an agent that reads untrusted files all day.

So getting the timing right is required and does not finish the job. A note delivered at the perfect moment still has to be believed, and a note the agent cannot check competes with the agent's own judgment on the agent's terms. Which memories should stop being advice and become checks, which need no belief at all, is worked through in When a Memory Should Become a Check.

07

What This Predicts for Agent Memory Delivery

Prediction 1. Holding the note's content fixed, a note retired on the action it concerns will change behaviour more often than the same note retired on delivery. The comparison is the two retirement rules, with nothing else varied, on scenarios where reading precedes editing by several turns. The recheck in Section 06 changed three things at once and cannot answer this.

Prediction 2. Repeating an unchanged note after the agent has ignored it will not raise compliance. Delivering it again at a new instance of the action it concerns will. The measurement is compliance per exposure, split by whether the exposure coincided with a new action.

Prediction 3. A message that fires regardless of state will be acted on at a declining rate across a session; a state-gated message will not. Plotting action rate against exposure count, for the same message under both policies, would show the difference, and would test whether habituation is the right word for what models do or only a useful analogy.

Close
The Line to Keep

If I had to keep one rule from all of this, it would be to end a note's eligibility on the action it is about, never on the send. A cooldown keyed to the send protects the reader and leaves the decision to chance; keyed to the action, it protects both, provided the channel's persistence is taken into account when deciding how often to resend.

The other rule is about evidence. Count a delivery where it was supposed to matter, at the decision. Each failure above was logged as a delivery. A log line written at the send can be wrong, as the first one was, and even when it is right it says nothing about whether the note was there when the edit was chosen. The command half of the policy, retiring a note when its command runs and renewing it at the next distinct run, is still unbuilt in vectr, and it is the next place I would expect the same failure to show up.

↑ Back to top
08

Sources

  • Rankin, C. H., et al. Habituation revisited: An updated and revised description of the behavioral characteristics of habituation. Neurobiology of Learning and Memory 92(2):135-138, 2009. doi:10.1016/j.nlm.2008.09.012. The definition of habituation, the "simplest form of learning" phrasing, and characteristics 1 to 4 as quoted in Section 01.
  • Thompson, R. F., Spencer, W. A. Habituation: A model phenomenon for the study of neuronal substrates of behavior. Psychological Review 73(1):16-43, 1966. doi:10.1037/h0022681. The original list of habituation's defining characteristics, revised by Rankin et al.
  • Sendelbach, S., Funk, M. Alarm fatigue: a patient safety concern. AACN Advanced Critical Care 24(4):378-386, 2013. PMID 24153215. The 72% to 99% false-alarm range, from the abstract.
  • The Joint Commission. Sentinel Event Alert, Issue 50: Medical device alarm safety in hospitals. 8 April 2013. The 85 to 99 percent estimate, the description of desensitisation and unsafe alarm settings, and the 98 voluntarily reported events with 80 deaths.
  • Tariq, S., Baruwal Chhetri, M., Nepal, S., Paris, C. Alert Fatigue in Security Operations Centres: Research Challenges and Opportunities. ACM Computing Surveys 57(9), 2025. doi:10.1145/3723158. Alert fatigue and burnout in SOCs, and remedies through automation, augmentation and human-AI collaboration, as summarised in the abstract.
  • Ndichu, S., Ban, T., Ozawa, S., Takahashi, T., Inoue, D. AI-Driven Security Alert Screening and Alert Fatigue Mitigation in Security Operations Centers: A Survey. arXiv:2605.08316, 2026 (preprint). The definition of alert correlation as a volume reducer, Section 3.3.1.
  • Cacioppo, J. T., Petty, R. E. Effects of message repetition and position on cognitive response, recall, and persuasion. Journal of Personality and Social Psychology 37(1):97-109, 1979. doi:10.1037/0022-3514.37.1.97. Agreement rising then falling with exposure, and the matching changes in counterargument and topic-irrelevant thought.
  • Pechmann, C., Stewart, D. W. Advertising Repetition: A Critical Review of Wearin and Wearout. Current Issues and Research in Advertising 11(1-2):285-329, 1988. doi:10.1080/01633392.1988.10504936. The wear-in and wear-out framing.
  • Benway, J. P. Banner Blindness: The Irony of Attention Grabbing on the World Wide Web. Proceedings of the Human Factors and Ergonomics Society Annual Meeting 42(5):463-467, 1998. doi:10.1177/154193129804200504. Distinctive banners overlooked by users searching for the information they held.
  • Wu, Y., Zhang, L., Zhou, Y., Wang, M., Peng, B., Li, S., Fan, X., Zhao, Z. Remember When It Matters: Proactive Memory Agent for Long-Horizon Agents. arXiv:2607.08716, 2026. Behavioral state decay, and selective intervention against always-on injection in the ablations.
  • Bui, N. D. Q. Building Effective AI Coding Agents for the Terminal: Scaffolding, Harness, Context Engineering, and Lessons Learned. arXiv:2603.05344, 2026. Event-driven system reminders against instruction fade-out.
  • vectr, commits on the reminder footer: f120846 (every-response firing and its cost), bd98d0f (the state counter and one banner per response), fa99f19 (the token gate and soft-then-escalate). Section 02.
  • vectr, commits on proxy delivery: 6272095 (charging on confirmed delivery, the audit split and the two documented residuals), 41def47 (note bodies and event-anchored retirement), 6720092 (the cooldown time limit), 78aba84 (the per-turn injection ledger and the semantic cooldown). Sections 03 to 05.
  • vectr, CHANGELOG.md, entries 1.5.0, 1.6.0, 1.7.0 and 1.11.0. The per-turn ledger, the two cooldown-identity changes, confirmed-delivery charging, event-anchored retirement and the time limit.
  • vectr, benchmarks/injection_utility/README.md. The zero-of-four delivery rate and its request capture, the zero-utility table and its three causes, 6 of 7 cells out of context before the first edit, the hook-channel cells, and the recheck after the fixes.
  • vectr source at commit 726e798: can_append_context, the event-anchored retirement block, TriggerFireLedger, TurnInjectionLedger, _existing_turn_ledger, and the cooldown settings in config.yaml (semantic) and (proxy). The append restriction and its three reasons, the retirement exemption, the per-session and per-turn ledgers, the proxy's lookup miss, and the default values.