cd /news/developer-tools/your-agent-s-memory-needs-the-word-n… · home topics developer-tools article
[ARTICLE · art-116141] src=dev.to ↗ pub= topic=developer-tools verified=true sentiment=· neutral

Your agent's memory needs the word 'no' — and a way to prove nobody edited it

Selvedge, an append-only memory store for AI coding agents, released v0.3.11, adding a tamper-evident hash chain and a first-class 'reject' event type so agents can explicitly record abandoned paths and prove the log hasn't been altered. The update also ships an evaluator for expiration conditions, ensuring stored decisions know when they should be revisited.

read5 min views2 publishedAug 31, 2026

the expensive failure in AI-assisted coding isn't a bad line of code — linters and tests catch those. it's an agent confidently re-implementing something your team already tried and killed. that's been the selvedge pitch from the start: an append-only store where the agent logs its own reasoning at change time, so "we tried that and it broke revocation" survives the session that learned it.

v0.3.10 solved delivery — the memory now arrives at session start instead of waiting to be asked ("Delivery, Not Storage" [arXiv:2607.20972] measured why that matters: zero voluntary memory operations across 114 turns against a pre-seeded store, while deterministic injection landed every time).

v0.3.11 is about the two halves of the sentence "rejected paths, retained." first: making the rejection itself first-class. second: making retained something you can check instead of something you take my word for.

until now, selvedge could tell you a path was abandoned mostly by reading tea leaves: a remove

event near an add

, a proximity window, a heuristic confidence score. useful, but it's inference — and inference is exactly what this tool exists to replace with testimony.

three changes make abandonment a stated fact:

** change_type="reject".** the counterpart to

revert

, for paths never taken. revert

says "we tried this and rolled it back." reject

says "we considered this and decided against it" — no code was ever written, and the decision is still worth a permanent record, because the next session's agent will consider it too. no new MCP tool; it's a value on the existing log_change

.** prior_attempts grows an exact tier.** an attempt closed by an explicit

reject

or revert

event now reports confidence: "exact"

— the outcome is stated in the log, not inferred from proximity. the old heuristic drops to tiebreaker for attempts without a stated outcome. (if you filter on confidence

, accept exact

alongside proximity_high

— rows move.)** expires_when finally does something.** a rejection stored without the condition that would invalidate it is data that silently rots. the column shipped dormant in v0.3.8; v0.3.11 ships the evaluator, with a deliberately closed grammar — four shapes, validated at write time, everything else rejected rather than stored:

library:django>=5.0      # revisit when a named dependency reaches a version
entity:users.email:changes   # revisit when that entity next changes
date:2027-01-15          # revisit on a date
manual:security-review   # never auto-fires; a label for humans

selvedge stale

evaluates these locally — installed package metadata, the event log itself, and the clock. no network, no LLM, and no cleverness: a library:

condition whose package isn't locally observable comes back as manual_review

, not a guess, and a pre-release never counts as its final release. a decision that knows when it should die is a decision you can still trust in a year.

capture-time nudges close the loop: log a reject

or revert

with neither stale_when

nor expires_when

and the validator suggests recording the invalidating condition. it warns, never rejects — same posture as the secret-shape warnings.

here's the uncomfortable question under the whole product: selvedge's differentiator is that rejected decisions stay on the record. append-only. permanent. queryable. and until this release, that was a promise about our own conduct — nothing in the store could show you a row was the row the agent wrote.

v0.3.11 adds a tamper-evident hash chain. every logged event gets a SHA-256 chain record in a sidecar table, written in the same transaction, each record binding the previous one and its own sequence number. selvedge verify

gains two checks: chain_intact

recomputes the whole thing and fails hard — naming the exact sequence number — when a chained row was edited, deleted, or reordered out-of-band. chain_coverage

warns (never fails) about rows that predate the chain: unchained, not invalid.

the design problem worth a paragraph, because it generalizes past selvedge: some fields are late-bound. the commit SHA does not exist when the event is logged — the event describes the work that produces the commit, and a post-commit hook stamps it in afterward. a naive "hash the whole row" chain calls your own git hook an attacker. selvedge's cut: git_commit

sits outside the protected core, declared out loud in the attestation manifest — tolerable because a commit hash is independently checkable against git, which is itself a hash chain maintained by other software. everything else — reasoning, diff, entity path, change type, the supersede links — is chained. legitimate mutations don't break anything: migrate-paths

appends an amend

record, and the destructive-gated prune appends a tombstone

accounting for what it deleted. a gated prune verifies clean; a silent sqlite3 "UPDATE events SET reasoning=..."

does not.

and the honest scope, which is in the module docstring and belongs in this post too: this detects casual and accidental modification, and produces an independently verifiable export. it is not proof against a motivated local attacker. there's no key. someone who controls the file can recompute every digest. what the chain buys you is that nobody edits the record casually — no script, no well-meant cleanup, no buggy future code path mutates a decision without the next selvedge verify

naming the exact row.

we ate the dogfood on day one: selvedge's own store crossed its chain genesis with this release, and the first chained rows are the decisions behind v0.3.11 — including a real change_type="reject"

for the retroactive chain seal

command we decided not to ship, with the reasoning attached.

selvedge supersede

-d/--diff

, --revisit-after

, and --expires-when

(#31) — parity with selvedge log

, through the same size-bound and secret-shape checks.numbers: tests 984 → 1114, coverage 89.4%. the chain checks are mutation-verified — delete the threading checks and the suite goes red. the resident MCP tool-surface cost moved this release (4445 tokens core, 2.2% of a 200k window) because the rejection example and the expires_when

grammar now live in the tool docstrings agents actually see; that's the adoption bet, called out in the changelog.

pip install -U selvedge

. genesis is automatic on your first write; there's no migration and no new config keys. one expected surprise: selvedge verify

will warn about your pre-existing rows (chain_coverage

) — they're unchained, not invalid, and the chain deliberately makes no claim about rows that predate it. CI stays green by default.

pip install selvedge
cd your-project
selvedge setup        # detects claude code / cursor / copilot

open source, MIT, local-first, zero LLM calls in the core. the thing i most want field reports on this time: log a real rejection with an expires_when

, wait for it to fire, and tell me whether the revisit that surfaced was worth your attention.

── more in #developer-tools 4 stories · sorted by recency
── more on @selvedge 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/your-agent-s-memory-…] indexed:0 read:5min 2026-08-31 ·