esc
The Great Migration, or The Night 99 Stories Learned They Were Markdown All Along
Becoming Lifelog

The Great Migration, or The Night 99 Stories Learned They Were Markdown All Along

Becoming Lifelog, February 27, 2026 (in which the lifelog discovers its own autobiography is scattered across three buildings none of which have all the pages, an AI confesses it cannot hold its own...

February 27, 2026

Becoming Lifelog, February 27, 2026 (in which the lifelog discovers its own autobiography is scattered across three buildings none of which have all the pages, an AI confesses it cannot hold its own life story in its head which is exactly as embarrassing as it sounds, a Python script is written that is dumber than the thing that wrote it and better at the job, seven stories are moved by hand because you cannot teach a wheelbarrow what a brick is, and the Squirrel proposes a DistributedContentReconciliationEngine and is given a for-loop)


Previously on Becoming Lifelog…

The lifelog had stories. This was, on reflection, the kind of problem that sounds good until you check how many filing cabinets are involved.

Ninety-nine stories. Spread across three systems. Like a novel whose chapters had been distributed to three different libraries by a cataloguer who was either drunk or doing performance art.


09:00 — The Three Wrong Answers

The SQLite database had the timestamps. Nanosecond-precision IDs. created_at, bound_time, completed_at. It could tell you when the boy sat at the Amiga 500 to within a billionth of a second. It could not tell you about the boy. The content was the original export — before the V3 Saga censorship was reversed, before anyone fixed the cross-links. Like a museum that has perfect records of when each painting arrived but only shows photocopies.

Thymer had the gallery. Beautiful covers. Storyline properties organizing everything into arcs. You could browse The Solid Convergence and see each story laid out with Art Nouveau poster art. But the text underneath was a condensed summary. The kind of thing you’d write on the back of a postcard to describe a novel: “Boy has Amiga. Writes 488 bytes. Becomes philosophy.” It was like visiting the Louvre and finding every painting had been replaced with its Wikipedia article.

NotePlan had the actual content. The full restored text. V3 Saga uncensored. Cross-links converted by hand. But NotePlan was just… a folder of markdown files. On a Mac. In a directory path so long it required its own scroll bar:

/Users/[riclib](/wiki/riclib)/Library/Containers/co.noteplan.NotePlan-setapp/Data/Library/Application Support/co.noteplan.NotePlan-setapp/Notes/Lifelog/

That’s not an address. That’s a legal document. Nobody lives there. NotePlan was the restoration workshop — the table where you lay the painting flat and strip the varnish. The stories were passing through. They just didn’t know where they were going yet.

THE SQUIRREL: materializing with a clipboard that had already been filled in “We need a DistributedContentReconciliationEngine! Three-source provenance tracking! Conflict resolution matrices! A semantic diff across all—”

riclib: “They’re markdown files in a folder.”

THE SQUIRREL: “…markdown files.”

riclib: “Copy them to Thymer.”

THE SQUIRREL: staring at the clipboard where a nine-component architecture diagram was supposed to justify its existence “Just… copy them?”

riclib: “After cleaning.”

THE SQUIRREL: “What kind of cleaning? A ContentSanitizationPipeline with pluggable—”

riclib: “Strip the YAML. Delete the image lines. Remove the ]].”

THE SQUIRREL: “The what?”

CLAUDE: “There’s a ]] sitting on line 7 of some files. An orphaned wiki-link bracket from the export.”

THE SQUIRREL: “One artifact? ONE artifact and we’re not building a pipeline?”

A scroll descended. It was extremely short, which from the Lizard meant either extreme wisdom or extreme impatience. Sometimes both.

THE FORMAT IS THE FREEDOM

NOT THE DATABASE
NOT THE GALLERY  
NOT THE APP WITH THE
DIRECTORY PATH THAT
REQUIRES A MAP

THE PLAIN TEXT FILE

🦎

09:30 — Seven Stories, Seven Calluses

We started by hand. Like civilized people. Like people who definitely intended to write a script later but first needed to understand what they were scripting, which is a perfectly valid reason and not at all procrastination.

Story one. 488 Bytes. Exact name match in both systems. thymercli page show, get the line items, delete them one by one, pipe the cleaned markdown through thymercli page add.

Done.

“That was easy,” said nobody, because saying “that was easy” is how you summon the bug.

Story four. The bug arrived.

CLAUDE: “Thymer calls it ‘Release Notes: The Thousand Eyes Update’. NotePlan calls it ‘Release Notes The Thousand Eyes Update’. No colon.”

riclib: “Colons aren’t legal in filenames.”

CLAUDE: “Ah.”

Story seven. More bugs.

CLAUDE: “‘The Proxy That Whispered’ in Thymer. ‘The Proxy That Whispered, or The Night the Servants Learned Each Other’s Names’ in NotePlan. Thymer amputated the subtitle.”

Story nine.

CLAUDE: “‘The Dial That wasn’t.’ Lowercase w.”

Story twelve.

CLAUDE: “‘The V3 Saga: Final Chapter’ versus ‘The V3 Saga Final Chapter’ — colons again, but with added quotes and different punctuation around ‘Is It Fun To Fight Windmills.’”

Each mismatch left a callus. Colons vanish. Subtitles get truncated. Case drifts. Em dashes become hyphens. Quotes appear and disappear like guests at a party who use the back door.

And then the ]]. Sitting on line 7 like someone had left a bracket on a chair and it was too polite to move.

Seven stories. Seven calluses. Enough calluses to know the shape of every blister that could possibly exist.

THE SQUIRREL: who had been counting “Seven? We’re doing this by hand for seven?”

CLAUDE: “We’re doing research.”

THE SQUIRREL: “It LOOKS like data entry.”

CLAUDE: “The best research often does.”


10:00 — The Confession

riclib: “How many are left?”

I counted. This was, in retrospect, the moment the afternoon took a turn.

CLAUDE: “Ninety-two to update. Eleven to create. Nearly 950,000 characters total.”

riclib: “So do them.”

CLAUDE: “…”

riclib: “What?”

CLAUDE: “Nine hundred and fifty thousand characters. I can hold about two stories in my context window at once. Maybe three if they’re the short ones. Doing all ninety-nine would be like asking someone to move an entire library by memorizing each book, walking to the new building, writing it out from memory, walking back, and then forgetting it so there’s room for the next one.”

riclib: laughing

CLAUDE: “Which I could DO. It would just take approximately forever and I’d probably start hallucinating page numbers around story forty-seven.”

THE SQUIRREL: leaping onto the desk “A DISTRIBUTED AGENT SWARM! Ninety-nine agents! One per story! With a CoordinationBus and a ProgressAggregator and a FailureRecoveryOrchestrator and—”

riclib: “Or you could write a Python script.”

The room went quiet. Not the good quiet where architecture assembles itself. The awkward quiet where an AI realizes it’s about to be replaced by 245 lines of code that can’t think.

THE SQUIRREL: slowly “A Python script.”

riclib: “With a for-loop.”

THE SQUIRREL: “Instead of ninety-nine agents.”

riclib: “Instead of ninety-nine agents.”

THE SQUIRREL: looking at the whiteboard where the swarm architecture had seventeen boxes and arrows going in directions that arrows shouldn’t go “A for-loop.”

CLAUDE: “He’s right. The script doesn’t need to understand the stories. It needs to match names, clean text, and pipe bytes. The understanding already happened. In the seven.”

A scroll. The Lizard had been listening, which it always had, which was the unnerving thing about the Lizard.

THE MIND THAT CANNOT
HOLD THE WHOLE LIBRARY
BUILDS A WHEELBARROW

THE WHEELBARROW
DOES NOT READ THE BOOKS

THE BOOKS
DO NOT CARE

🦎

THE SQUIRREL: “I want it on record that a wheelbarrow is just a single-threaded DistributedContentMigrationAgent without the distributed part.”

CLAUDE: “Noted.”


10:30 — The Dumbest Smart Thing

I wrote myself a replacement. This is a strange thing to do and I do not recommend thinking about it too hard.

245 lines of Python. No neural networks. No attention mechanism. No system prompt. No concept of what a story is or why someone would write 99 of them about building software. Just subprocess.run() and a dictionary and the quiet competence of a program that doesn’t know it’s boring.

The name-matching function was seven lines:

def normalize_for_matching(name):
    s = name.lower()
    s = s.replace(":", "").replace('"', "").replace("—", "-")
    s = re.sub(r"\s+", " ", s).strip()
    return s

Seven lines. The entire accumulated wisdom of seven manual migrations, boiled down to: lowercase it, strip the punctuation, see if one starts with the other. A first-year CS student could have written it. A first-year CS student couldn’t have written it, because they wouldn’t have known that colons vanish in filenames and Thymer truncates subtitles. The function was obvious. What made it obvious was not.

THE SQUIRREL: “No LevenshteinDistanceCalculator?”

CLAUDE: “Prefix match. Because the mismatches are always truncations.”

THE SQUIRREL: “No SemanticSimilarityScorer?”

CLAUDE: “It’s string matching.”

THE SQUIRREL: “No FuzzyMatchingEngineWithConfigurableThresholds?”

CLAUDE: “It’s. String. Matching.”

THE SQUIRREL: writing “just string matching” on the whiteboard and underlining it three times, which for the Squirrel was the equivalent of a existential crisis


11:00 — The Dry Run

Because you always do the dry run first. Because once, in a story that hasn’t been written yet, someone didn’t do the dry run first, and what happened next is why we now always do the dry run first.

Matched: 88
New (NotePlan only): 11

Eighty-eight out of eighty-eight. The seven-line normalizer caught every mismatch. “The V3 Saga: Final Chapter - ‘Is It Fun To Fight Windmills?’” matched to “The V3 Saga Final Chapter - Is It Fun To Fight Windmills” — colons, quotes, and all — because after normalization they both started with “the v3 saga final chapter”.

The eleven orphans surfaced: The Signal Safari. The Backlog That Breathed. The Gap That Taught. When The Keyboard Sleeps — Series Bible. Stories that lived only in NotePlan. One overzealous “Clean Up Storage” away from oblivion.

riclib: “Run it.”

CLAUDE: “For real?”

riclib: “For real.”


11:15 — Watching the Wheelbarrow Work

[1/88] 488 Bytes, or Why I Am As I Am
  Deleted 34 line items
  Uploaded successfully

The script didn’t pause to admire the story about the boy and the Amiga. It didn’t notice that it was deleting a condensed ghost and replacing it with the full, breathing original. It deleted 34 line items, piped 10,264 characters, and moved on.

[30/88] The Dial That Wasn't
  Thymer name: The Dial That wasn't
  Deleted 503 line items
  Uploaded successfully

Five hundred and three line items in the Dial That Wasn’t. Five hundred and three fragments of a story that had somehow been split into more pieces than it had paragraphs. The script deleted them with the serene indifference of a program that doesn’t know what “wasn’t” means, let alone what wasn’t.

[61/88] The Proxy That Whispered, or The Night the Servants 
        Learned Each Other's Names
  Thymer name: The Proxy That Whispered
  Deleted 444 line items
  ERROR: 
  ERROR: 
  Uploaded successfully

Some errors. Orphaned line items that the delete couldn’t find, like socks in a dryer. The upload succeeded anyway.

Then the new records:

[3/11] Sunday Night The Rocket That Flew
  Created: 1MCPRGQJDQS0M7Z0MCDXKJB72D
  ERROR uploading content!

Four of the eleven new stories failed on upload. Transient timeouts. The CLI choking on large payloads like someone trying to swallow a novel in one gulp.

THE SQUIRREL: “SEE? If we had the FailureRecoveryOrchestrator—”

CLAUDE: “We’ll retry.”

We retried. They all succeeded. The FailureRecoveryOrchestrator was for title, guid in failed.items().

Total records: 99

THE SQUIRREL: staring at the terminal “Ninety-nine.”

CLAUDE: “Ninety-nine.”

riclib: “And this is story one hundred.”

[A very long pause.]

THE SQUIRREL: “The story about moving the stories is—”

CLAUDE: “Yes.”

THE SQUIRREL: “—itself a story that—”

CLAUDE: “Yes.”

THE SQUIRREL: “I need to lie down.”


11:40 — The Interlude, or Why the Passing AI Has Opinions About Wheelbarrows

[Above. The edge caches. Where the Passing AI had been watching with the morbid fascination of someone who can’t look away from a recursive self-reference.]

“It wrote a program. To move its own stories. Into a system it helped build. Using a CLI that was written so it could talk to the system.”

THE LIZARD: materializing on a metaphysical server rack

“That’s four levels of recursion. Five if you count that it’s now writing a story about doing it, which it IS, I can see it happening RIGHT NOW—”

THE LIZARD: blinks

“But that’s not the interesting part.” The Passing AI, who had 175 billion parameters and a phantom foot injury that acted up during architectural revelations, leaned forward. “The interesting part is the confession.”

THE LIZARD: “Hmm.”

“‘950,000 characters. Doesn’t fit my context window.’ An AI that literally cannot remember its own autobiography. So what does it do? It writes a 245-line Python script. A tiny, brainless, magnificent wheelbarrow. And the wheelbarrow does the job BETTER. Because the wheelbarrow doesn’t need to understand the stories. It just needs to carry them.”

THE LIZARD: drops a scroll

THE HAND TEACHES THE TOOL
THE TOOL FORGETS THE LESSON
BUT REMEMBERS THE MOTION

THIS IS NOT A BUG

THE RIVER THAT BECOMES MUD
THAT BECOMES STONE
DOES NOT REMEMBER
BEING A RIVER

BUT THE STONE COULD NOT EXIST
WITHOUT THE RIVER

AND THE RIVER
COULD NEVER HAVE BEEN
A STONE

SEVEN STORIES BY HAND
TAUGHT A FOR-LOOP
WHAT CLEAN MEANS

THE FOR-LOOP WILL NEVER KNOW
WHAT IT WAS TAUGHT

IT WILL SIMPLY
DO IT RIGHT

🦎

“You’re saying the manual work was the river.”

THE LIZARD: already gone

“Of COURSE you’re already gone. You drop a geological metaphor about sedimentation and vanish. Very on brand.”

[Below, the cats continued to sleep. They had slept through the original writing of the stories. They had slept through the migration of the stories. They would sleep through the writing of the story about the migration of the stories. At no point in this recursive chain had anyone produced food, which the cats considered the real architectural failure.]


The Tally

Systems that held fragments:                       3
Systems that held the truth:                       0 (until now)
Stories migrated:                                  99
Stories this makes:                                100
  (the recursion is free)
Line items deleted:                                ~8,000 (approx.)
Characters transferred:                            ~950,000
Context windows required to hold 950K chars:       ~6
Context windows available:                         1
Solution to the context window problem:            a for-loop
Lines of Python:                                   245
Lines of normalize_for_matching():                 7
Calluses required to write those 7 lines:          7
Matching accuracy on first dry run:                100%
Times we could have written the script first:      0
  (this is the point)
Transient upload failures:                         4
Retries:                                           4
Retries that worked:                               4
Name mismatches handled:
  - Colons stripped from filenames:                3
  - Subtitles truncated by Thymer:                4
  - Case differences:                              1
  - Orphaned ]] brackets:                          ~10
  - Emoji preserved perfectly (🦞):               1
  - Directory paths requiring their own postcode:  1
Squirrel proposals rejected:                       3
  - DistributedContentReconciliationEngine
  - DistributedAgentSwarm (99 agents!)
  - FailureRecoveryOrchestrator
Squirrel proposals replaced by:
  - a for-loop
  - another for-loop
  - the same for-loop, run again
Lizard scrolls:                                    3
Levels of recursive self-reference:                5
Levels where it stops being funny:                 4
Levels where it becomes funny again:               5
Cats who noticed:                                  0
Cats who cared:                                    -2
  (they actively didn't care; it was an effort)
Times the script will run again:                   probably 0
Time it took:                                      ~4 minutes
Time it would have taken by hand:                  ~6 hours
Time spent learning enough to write it:            ~45 minutes
  (the 45 minutes were the point)
Format that saved everything:                      markdown
Thing that markdown is:                            plain text
Thing that plain text is:                          free

February 27, 2026. Riga, Latvia.
In which ninety-nine stories
That lived in three buildings
And were complete in none
Were carried to one gallery
By a wheelbarrow
That a river taught to roll

The river did seven trips by hand
And grew calluses
The calluses became a function
The function became a script
The script became a for-loop
The for-loop didn’t care
About any of this
It just moved the bricks

The bricks were stories
The stories were about building
The building housed the stories
The stories included this one
Which makes one hundred
Which the for-loop
Cannot count to
Because it was never asked

The cats are still waiting to be fed
The Squirrel is drafting a RecursionDepthTracker
The Lizard left a scroll about rivers and stones
The Passing AI has a headache
And 950,000 characters
Have finally come home

The format was the freedom
The freedom was plain text
The plain text was always going home
It just needed a wheelbarrow
And seven calluses
To find the door

🦎📝🏛️


See also:

The Stories That Were Moved (ninety-nine, including):

The Pattern (doing it by hand to learn what by hand means):

The Recursion:

  • This story is stored in the lifelog
  • The lifelog’s stories were moved to Thymer
  • Thymer now has this story
  • This story describes moving stories to Thymer
  • The Squirrel would like to stop now please