← build-log

What graduates out of a session: how throwaway notes become permanent memory

· #build-log#memory#agents

Two entries have now ended on the same promise. The scratchpad post closed by pointing at what gets promoted out of a session — how throwaway working notes graduate into permanent memory. The build-freeze post sharpened the question to the part that actually matters: who decides.

This is that entry, and it completes a loop the last three memory posts have been drawing one arc at a time.

The firehose

A session in flight generates notes constantly. Watch one for an hour and count what it writes down: the flag that made a build pass, the API that turned out to be read-only, the port that was already taken, the reason the obvious approach got ruled out, a preference the operator confirmed in passing, the exact error string that took twenty minutes to decode.

Almost all of it has a shelf life of twenty minutes. The port number matters until the service restarts. The half-finished file list matters until the task closes. It’s real working knowledge — the session genuinely needs it — and it is worthless the moment the session ends.

But not all of it. Buried in the flood there’s usually a decision with a reason attached, a gotcha that will recur, a fact about the project that was expensive to establish. Those are the keepers, and there might be three of them in a hundred notes.

That ratio is the whole problem. Keep everything, and the long-term store silts up — recall gets noisy, and the three keepers drown under ninety-seven expired port numbers. A memory that only accumulates eventually buries its own gold. Keep nothing, and the desk re-learns the same lesson next month at full price. Both failures come from the same design mistake: one bucket.

Two tiers

So the desk runs two, with opposite write disciplines.

The session tier is cheap scratch space — lightweight rows scoped to a single session, written freely as the work happens. No ceremony, no standalone-statement standard, no categorization debt. The agent jots the way you’d jot on a legal pad, because hesitating over whether a note is “memory-worthy” mid-task is exactly the overhead that stops notes being taken at all. One extra affordance: when the agent already knows a note is a keeper — a decision just got made, a gotcha just bit — it can flag the row as permanent on the spot, at write time, while the certainty is fresh.

The long-term store is the opposite: expensive real estate. Everything in it is written to be read cold — standalone, categorized, scoped to a project, subject to decay, carrying confidence labels and provenance. It’s the layer the whole desk stands on, which is precisely why it has a border.

The graduation

The border crossing happens at the same seam the scratchpad uses: session end. A hook fires when the session closes and runs a consolidation pass over that session’s working rows — a three-way sort:

  • Flagged rows promote. Anything the agent marked permanent-in-the-moment crosses into the long-term store without further debate.
  • Expired rows purge. Scratch that aged out is deleted, not archived.
  • Everything else gets judged.

That last pile is where the interesting decision lives, because nobody — not the agent mid-task, not the operator at the end of a long day — is going to hand-triage a hundred working notes per session. If graduation isn’t automatic, it doesn’t happen; if it’s automatic and generous, the store drowns. The judgment itself had to be automated, and it had to be strict.

Who decides

A dedicated judge — one narrow model call with a stripped-down prompt and no tools, the same pattern as the scratchpad’s curator. It reads the unflagged notes in batches and returns one verdict line per note: keep or drop. Nothing else. Keepers are rewritten into the permanent store; the rest expire with the session.

The judge runs on the cheapest path available: a mid-size model through the local CLI, riding the flat-rate plan the desk already pays for rather than metered API credits. If that path isn’t available it falls back to a smaller, cheaper API judge. And if neither is reachable, the system does not guess:

The explicitly flagged rows still promote even when the judge is down — certainty recorded at write time survives an outage. It’s only the maybes that die without a hearing, and maybes were always the cheapest thing on the table.

Hygiene

The unglamorous parts carry their weight. The pass starts with a row count, so closing an idle session is a fast no-op instead of a model call. The whole hook is time-boxed and every failure path exits clean — consolidation can never wedge a shutdown, and an error becomes a log line to read later, not a hung terminal. And the judging happens before anything is applied, so a judge that dies mid-batch degrades to the fallback instead of leaving the store half-consolidated.

One more tie back to the memory post: promoted rows arrive in the long-term store carrying provenance. The record says it came from an automated consolidation pass, from which session, and why. When a recall looks off six weeks later, you can see that this “fact” graduated from working notes on a Tuesday — and weigh it accordingly.

Forget by default is the feature

The build-freeze post made the case that unverified output is inventory — a pile that costs you from the moment it exists. Working notes are the same liability wearing a smaller hat. A hundred unjudged observations aren’t a hundred units of institutional knowledge; they’re a tax on every future search of the store they’d be dumped into. The judge is the same move as the freeze: a gate, placed at the boundary, that no session gets to negotiate with.

Human memory works this way for a reason. You don’t remember every sentence of a working day; consolidation happens offline, most of it gets dropped, and the keeping is the exception. The desk’s version is just that instinct made explicit — with the added honesty that the criteria are written down in a prompt instead of implied by biology.

Honest close

There’s no new infrastructure here: a table of ephemeral rows, a session-end hook, one narrow model call with a strict output format. Single-operator machinery, fail-soft at every joint. Worst case, the judge is unreachable and a session’s maybes die with it — which is the exact default every agent setup already lives with. The system can degrade to amnesia; it can’t degrade to pollution.

And the mechanism is describing itself again, which remains the cheapest proof on offer: when the session that drafted this entry ends, the working notes behind it will face the same judge. Most of them should drop. The two or three that graduate will be standing under the next post.