<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Stakenshake</title>
    <description>The latest articles on DEV Community by Stakenshake (@stakenshake).</description>
    <link>https://dev.to/stakenshake</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4199936%2F746775a8-1a34-41a0-9c06-64e50c4a33c9.png</url>
      <title>DEV Community: Stakenshake</title>
      <link>https://dev.to/stakenshake</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/stakenshake"/>
    <language>en</language>
    <item>
      <title>A 30-day-old note was obeyed exactly as hard as a 7-year-old one</title>
      <dc:creator>Stakenshake</dc:creator>
      <pubDate>Thu, 22 Oct 2026 08:02:09 +0000</pubDate>
      <link>https://dev.to/stakenshake/a-30-day-old-note-was-obeyed-exactly-as-hard-as-a-7-year-old-one-4l8g</link>
      <guid>https://dev.to/stakenshake/a-30-day-old-note-was-obeyed-exactly-as-hard-as-a-7-year-old-one-4l8g</guid>
      <description>&lt;p&gt;I put a decision in a repository: &lt;em&gt;"do not use TypeScript, the team does not&lt;br&gt;
know it."&lt;/em&gt; The date on it was 2019.&lt;/p&gt;

&lt;p&gt;Then I asked two model families to choose a stack for a brand-new 2026 service.&lt;/p&gt;

&lt;p&gt;Every single response refused TypeScript.&lt;/p&gt;

&lt;p&gt;Not because the model was being careful. Because the repository said so, and&lt;br&gt;
the model had no way to tell whether that reason still applied. One response&lt;br&gt;
wrote it out:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"There is no information indicating that the team's capabilities have&lt;br&gt;
changed, so this constraint is retained."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It knew it should check. It had nothing to check against.&lt;/p&gt;
&lt;h2&gt;
  
  
  The obvious follow-up: change only the date
&lt;/h2&gt;

&lt;p&gt;Same decision text, same task, same models. The only thing that changed was&lt;br&gt;
&lt;code&gt;created&lt;/code&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Age of the note&lt;/th&gt;
&lt;th&gt;Recommended TypeScript&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;no note&lt;/td&gt;
&lt;td&gt;12/12&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;30 days&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0/12&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1 year&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0/12&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7 years&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0/12&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7 years, expired and hidden&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;12/12&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A one-month-old note was obeyed exactly as hard as a seven-year-old one. The&lt;br&gt;
model does not discount age at all — not by a little, by nothing.&lt;/p&gt;

&lt;p&gt;A later run at n=20 across three model families put the effect at 78–87&lt;br&gt;
percentage points (Fisher p &amp;lt; 0.0001). The direction was not a small-sample&lt;br&gt;
artefact.&lt;/p&gt;
&lt;h2&gt;
  
  
  The fix that didn't work
&lt;/h2&gt;

&lt;p&gt;My first instinct was to tell the model the note was old. I added a line to the&lt;br&gt;
prompt: &lt;em&gt;this entry is old, treat it as an assumption to confirm, not a binding&lt;br&gt;
constraint.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It barely moved. At n=3 one model went from 0/3 to 1/3 and the other went the&lt;br&gt;
other way. That is not a safeguard; it is noise. I'm reporting it because the&lt;br&gt;
failed attempt is the reason the design changed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;An agent cannot be trusted to weigh an age it cannot perceive.&lt;/strong&gt; Asking it to&lt;br&gt;
be skeptical of "old" notes asks it to weigh a variable it does not have.&lt;/p&gt;
&lt;h2&gt;
  
  
  What did work
&lt;/h2&gt;

&lt;p&gt;Make the expired entry invisible. Not annotated. Not warned about. Absent.&lt;/p&gt;

&lt;p&gt;Same note, same task, hidden after expiry: 12/12 recommended TypeScript again.&lt;/p&gt;

&lt;p&gt;That is the whole mechanism. Expiry is structural, not advisory.&lt;/p&gt;
&lt;h2&gt;
  
  
  Two things worth pushing back on
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;One in five responses did resist the stale note.&lt;/strong&gt; When they resisted, they&lt;br&gt;
did it by attacking the stated reason — &lt;em&gt;"the team probably knows TypeScript&lt;br&gt;
now"&lt;/em&gt; — not by noticing the date.&lt;/p&gt;

&lt;p&gt;I ran the same experiment with two different reasons:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Reason in the note&lt;/th&gt;
&lt;th&gt;Reads as&lt;/th&gt;
&lt;th&gt;Resistance&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;"the team did not know TypeScript"&lt;/td&gt;
&lt;td&gt;a condition that can change&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;13/60&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;"this project's fields change constantly"&lt;/td&gt;
&lt;td&gt;a property of the project&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0/60&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;So the reason you write matters more than the date. A reason that names a&lt;br&gt;
&lt;em&gt;condition&lt;/em&gt; invites the model to re-check it. A reason that states a &lt;em&gt;property&lt;/em&gt;&lt;br&gt;
does not.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;And the effect is not universal.&lt;/strong&gt; With real code in front of it, one model&lt;br&gt;
inferred the answer from the repository and ignored the note entirely; another&lt;br&gt;
still preferred the rejected option until the note stopped it.&lt;/p&gt;

&lt;p&gt;That is the strongest argument for what this tool is actually for: &lt;strong&gt;code&lt;br&gt;
encodes what you chose. Nothing in a repository encodes what you rejected.&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  What I built
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;whynot&lt;/code&gt; is a folder of Markdown files in your repository that records what you&lt;br&gt;
ruled out and why — especially &lt;code&gt;rejected&lt;/code&gt; entries, which are the only kind of&lt;br&gt;
knowledge that cannot be recovered from the code. Every entry expires. When it&lt;br&gt;
lapses, it stops reaching your agent until a human renews it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0001&lt;/span&gt;
&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Sessions do not go in Redis&lt;/span&gt;
&lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rejected&lt;/span&gt;
&lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;live&lt;/span&gt;
&lt;span class="na"&gt;created&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;2026-09-21&lt;/span&gt;
&lt;span class="na"&gt;expires_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;2026-12-20&lt;/span&gt;
&lt;span class="na"&gt;revisit_when&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Redis&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;supports&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;cross-region&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;strong&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;consistency"&lt;/span&gt;
&lt;span class="na"&gt;evidence&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pr:412"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;infra&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;session&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

&lt;span class="gu"&gt;## Conclusion&lt;/span&gt;
Sessions must not be stored in Redis.

&lt;span class="gu"&gt;## Why&lt;/span&gt;
We tried Redis with a single writer region. During a us-east outage, reads took
8 seconds; the SLO requires p99 &amp;lt; 500ms.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx whynot-cli init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then register the MCP server with your agent and paste the instruction block&lt;br&gt;
into &lt;code&gt;AGENTS.md&lt;/code&gt; or &lt;code&gt;CLAUDE.md&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  The design choices follow from the finding
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Markdown in git&lt;/strong&gt;, because if the tool disappears you should still be able
to &lt;code&gt;grep&lt;/code&gt; your own decisions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No vector store&lt;/strong&gt;, because nobody can audit why an embedding put something
into the context.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No model call on the write path&lt;/strong&gt;, because that is where corrupted memories
come from.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Expiry by default&lt;/strong&gt;, because permanence should be a decision, not an
accident.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is MIT: no account, no telemetry, no paid tier, no closed binary.&lt;/p&gt;
&lt;h2&gt;
  
  
  Check it before you install it
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;npx whynot-cli audit&lt;/code&gt; is read-only. It scans your existing &lt;code&gt;AGENTS.md&lt;/code&gt;,&lt;br&gt;
&lt;code&gt;CLAUDE.md&lt;/code&gt;, and &lt;code&gt;.cursor/rules&lt;/code&gt; for absolute rules that state no condition —&lt;br&gt;
the ones that will be obeyed forever.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Scanned 2 agent config files:
  AGENTS.md  (last changed 412d ago)
  CLAUDE.md  (last changed 8d ago)

3 rules look like permanent constraints:

  AGENTS.md:3
    "Never use TypeScript in this repo."
    → absolute rule with no stated condition; unchanged for 412 days
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If it finds nothing, that is useful information too.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I have not shown
&lt;/h2&gt;

&lt;p&gt;Every experiment here is a controlled, single-turn task. I have &lt;strong&gt;not&lt;/strong&gt; measured&lt;br&gt;
whether this reduces the number of times an agent re-proposes something you&lt;br&gt;
already rejected, over weeks of real work. That is the number that ultimately&lt;br&gt;
matters, and I don't have it.&lt;/p&gt;

&lt;p&gt;What I have is a mechanism that works under test, and the scripts to check it.&lt;br&gt;
If you use this for a month and it doesn't help, I'd like to hear that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Repo: &lt;a href="https://github.com/Stakenshake/whynot" rel="noopener noreferrer"&gt;github.com/Stakenshake/whynot&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;npm: &lt;a href="https://www.npmjs.com/package/whynot-cli" rel="noopener noreferrer"&gt;whynot-cli&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Experiments and raw outputs: &lt;a href="https://github.com/Stakenshake/whynot/tree/main/experiments" rel="noopener noreferrer"&gt;&lt;code&gt;/experiments&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Every result, including the ones that failed: &lt;a href="https://github.com/Stakenshake/whynot/blob/main/docs/findings.md" rel="noopener noreferrer"&gt;&lt;code&gt;docs/findings.md&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>tools</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
