R.02 · From the Studio

What the FolderForgets

There is a file on my machine that tells an agent it may not send email.

It does not ask it to refrain. It says the capability does not exist, that if asked the agent should say so, and that it should not describe this as a policy it is choosing to follow. I did not write that line this week. I ported it from a system I built in July, where it had already survived one rewrite, and I kept the wording exactly because rewording a law that works is how it stops working.

Yesterday I stood up a new office on top of it in an afternoon. Thirteen files moved across almost unchanged. Three were rewritten. Three were deleted on purpose, because the thing they did belongs to a different system and having two of them would mean having neither.

That is the method. It is less about AI than it sounds.

The question people actually ask

Someone asked me last week what the difference is between my folders and agents. It is a fair question and the honest answer is that there is no difference, because the folders are what the agents read. The dichotomy is false and worth dismantling before anything else, because the interesting distinction is hiding behind it.

The real question is where the judgment lives.

In the ordinary setup, judgment lives in the model at runtime. You write a system prompt, hand it some tools, give it a goal, and it works out how. The behaviour is emergent. When it does the wrong thing you add a sentence to the prompt and hope. What the system knows is split between the weights, which you cannot inspect, and one block of text that grows by accretion until nobody can say what is in it.

In mine, the judgment is written down where I can read it, and the model reads it too. The model brings fluency. The folder brings the rules, the boundaries, and the things that were learned the expensive way.

What is actually in a folder

Start with the thing that is not a prompt. A rule in one of these systems does not say "write a good reason for contacting this person." It says a reason has three parts, the fact, its source, and the connection to the recipient. Missing the fact it is flattery. Missing the source it is an assumption. Missing the connection it is trivia. Then it gives the test, and then, underneath, a dated note saying what the first version of the rule got wrong and when that was corrected.

Four properties come out of writing rules that way.

Every rule has an identifier, and every file has one line saying what it owns and what it does not. That second half is the load-bearing one. A file that says "does not own the letter's register, that belongs elsewhere" cannot quietly expand into a second opinion on register. When two files disagree, a stated hierarchy decides, rather than whichever instruction happened to sit nearer the end of the prompt.

A route names the files to be read, in order, before the work starts. Not all of them. The specific ones. One system here has thirty routes and a generated table of what each costs against its ceiling, because a room with no walls is not a room.

State has one writer. In the office I built yesterday there are five different names for five different things, and each has exactly one file permitted to write it. A classification of an incoming reply never sets the status of the conversation directly. It proposes, and one other file converts confirmed proposals into state. Two parts of a system can then never record different truths about the same event, which is not a discipline you can maintain by intention.

And a change to behaviour is a diff. Someone who does not read code can review a change to how a system behaves, because the change is a paragraph of English in a pull request. That has been the single most useful property, and it is the one I did not predict.

THE WHOLE FOLDER THE ROUTE 01 · POSITION 02 · HIERARCHY 03 · THE RULE 04 · REFUSALS
Fig. 02.1 · A route is a selection, not a volume

What it costs

Every route loads files, and files are tokens, which is why the ceilings exist. The rules are only as good as the writing, so vague prose produces vague behaviour and terse normative prose is not a style choice.

And there is no compiler. Two files can disagree and nothing catches it. Building that office yesterday, one file called a step by its old name while the file that owns the sequence had renamed it, and a field called authority meant two incompatible things in two places, one of which explicitly forbade what the other was doing. A human found both. Markdown has no type system, and I have stopped pretending that reading carefully is a substitute for one.

What the folder cannot do

A folder holds what is true. It does not hold what happened.

It can tell an agent that a decision must cite its source and its date. It cannot tell it what was decided in August, or that the decision was reversed in September, or that the approach it is about to suggest was already tried and abandoned in July by a session nobody remembers. The constitution is not the minutes.

That gap is where everything got expensive. Context windows end. A session closes and its reasoning goes with it. Three weeks later the same question arrives and gets answered again, differently, with the same confidence. I lost more time to that than to any modelling problem.

The ledger

So there is a second layer, which is a ledger rather than a document. I called it memnant, for the remnant of memory that survives after a context window dies, and it is MIT licensed and on npm if any of this is useful to you. One SQLite file per repository, ignored by git, holding typed records: decisions, fixes that worked, session logs, rejections. Each record carries when it was written, what it superseded, and an embedding so that related records find each other on the way in.

The distinction that matters is in its own documentation, and it is the sentence I would keep if I had to throw the rest away. Notebooks accumulate. Ledgers stay true.

A notebook is flat, hand-curated, and never invalidated. Nothing in a project instruction file tells you the note from March is wrong now. A ledger is append-only, and when the code moves underneath a decision, the decision is flagged rather than served as current. A stale decision injected confidently into context is worse than a forgotten one, which is the actual argument, and it is the opposite of the way most memory features are sold. Remembering was never the hard part.

Rejections earn their own tag, which is the feature I use most and mention least. A system left alone will agree with you. Recording what failed is the only reliable way to stop a future session retrying it with fresh enthusiasm and a clean context window.

Across repositories there is one more file, a shared store that fixes and rejections get promoted into automatically. A problem solved once in an events platform surfaces in an iOS app eight weeks later. Seven hundred and forty eight records in it now, drawn from thirty two different projects.

SUPERSEDES STALE RECORDS TIME THE CODE CODE MOVED
Fig. 02.2 · A ledger flags rather than serves

Four behaviours borrowed from ants

That shared store is not a convenience bolted on the side. It is the smallest visible piece of a design I spent a whole phase on, which takes four behaviours from ant colonies so that knowledge compounds with use, spreads without anyone coordinating it, and corrects itself.

Pheromone trails. Records that keep being recalled together get boosted together, and trails nobody walks decay. Nothing declares the pairings. They form.

Stigmergy. Coordination by changing the environment rather than by sending messages. You touch a file, that fact is left behind in the ledger, and whoever works near it next sees what you did without anybody having told them.

Recruitment. A pattern only surfaces across projects once enough separate sessions have confirmed it independently. One sighting is noise.

Death spiral detection. In a real colony, ants following each other's trails can close a loop and circle until they die of it. The software version is a decision superseded in a ring, revised back to where it started, with everyone involved confident they are making progress.

I still think those are the right four. Here is what they produced.

REINFORCED DECAYING A LOOP THAT CLOSES
Fig. 02.3 · Trails reinforce, decay, and occasionally close

The numbers, including the bad ones

Thirty nine repositories on this machine carry a ledger. Between them, around seven thousand two hundred records and sixteen hundred sessions, the earliest from late March. Twenty four of the thirty nine have been written to in the last month. Twelve have gone quiet. Three were set up and never used, which is a fair rate and not one I would have guessed.

The largest is an events platform at two thousand one hundred records and forty megabytes, which is nineteen kilobytes a record, most of it embeddings. Every similarity operation is a full scan of the table in memory. The design note says not to optimise for five hundred thousand records because the target is five hundred. One repository is already at four times that and the note has not been revised, which is a decision I am now making by not making it.

Pheromone trails worked. Three thousand four hundred and twenty eight of them, laid down between records that kept coming back together. Nobody chose those pairings. They formed because I kept walking the same paths and the ones I stopped walking faded, which is the whole idea, working, without being asked to.

Recruitment almost did not. It needs three separate confirmations before a pattern is promoted. Of the seven hundred and forty nine records in the shared store, two have ever reached that.

Stigmergy has never run at all. Both of its queries require a record whose builder identifier is set and is different from mine. That field is null on all seven thousand two hundred records, because it is written by a command that configures a team, and I have never had one to configure. The query is not unlucky. It is structurally incapable of returning a row on this machine.

And contradiction detection, which the readme calls a differentiator, has produced nothing. Records link to each other by four kinds of edge. Related: three thousand eight hundred and seventy. Supersedes: one hundred and twenty. Version of: thirty one. Contradicts: zero.

TRAILS RECRUITMENT STIGMERGY CONTRADICTS 3428 2 0 0
Fig. 02.4 · Four behaviours, one colony member

Not a low number. Zero, across seven thousand records and six months.

A colony of one

It took me an embarrassingly long time to see that those are not three separate disappointments. They are one.

Stigmergy needs somebody else to leave traces for. Recruitment needs separate sessions arriving at the same conclusion apart from each other. Contradiction detection keys on the identifier of a second builder. Every one of them assumes a colony, which is to say many agents leaving marks that other agents later read.

There has only ever been me.

ONE
Fig. 02.5 · Every social behaviour, and one member

Trails worked because a single ant still walks its own paths, and a path walked twice is worth remembering whether or not anyone else is watching. Everything social had nobody to be social with. The design is not wrong. The population was one, and I built for a scale I did not have while believing I was already operating at it.

What I cannot defend is the six months. Nothing errored. An empty mechanism does not raise: it returns an empty list, the context compiler injects an empty section, and an empty section is indistinguishable from a section with nothing to report. That is the failure mode worth carrying out of this, and it is not specific to ants or to ledgers. A feature that cannot fire and a feature with nothing to say produce identical output, forever, and both of them read exactly like working.

I wrote a tool to catch decisions that quietly stopped being true, and never pointed it at its own readme.

The bottleneck, still

I have written before that somebody has to build the rooms. That is still what I think. What I would add is that a room is not enough on its own, because a room does not remember who was in it, and because a room built for a crowd tells you nothing about itself while it is empty.

The folder holds the law and the ledger holds the history, and the interesting failures live in the join. Nothing I have built yet notices when the ledger records a decision the folder forbids. That check does not exist. It is the obvious next thing and I have not written it, which I mention because a system whose argument is about stale claims should probably be the last one to publish a list of what it is definitely going to do next.