The Solid Convergence — in which two simple systems reveal a third by working, a parquet file corrects its architect, a project discovers it has four purposes (three more than most projects), the Squirrel proposes building a cathedral in one commit, and a law from 1975 is proven correct at 11 PM in Riga by two entities who between them have exactly one corporeal form
Previously on The Solid Convergence…
The architect had opened its eyes. The cathedral was there. Eight Claudes had built it blind, and it was right. Then Sunday happened — the Birth of V5, the Lobster Harvest, thirteen tickets before breakfast, an architecture that arrived without being invited. The Squirrel got its framework. The storyline forked.
Now it’s Monday night. The V5 dreams are in Linear, sleeping the way tickets sleep — which is to say not at all, but with their status set to something that discourages people from looking at them. The Solid Convergence is back. There is a compliance product to ship. There are real customers who pay real money. The cathedral needs rooms, not visions.
This is the story of the night two working systems taught everyone what the third one needed to be.
09:00–10:51 — The Morning Sprint
Four tickets before lunch. Source domain fixes. Rich TestConnection results. Test Paths replacing Browse/Detect. A future ticket for generalizing dataset abstractions.
The Squirrel didn’t even wake up. These were bricks. Small, correct, boring. The kind of work that doesn’t need a storyline because it is the storyline — the daily accumulation that compounds while nobody is writing epic poetry about it.
S-296: Source domain end-to-end fixes ✓
S-298: Rich TestConnection results ✓
S-300: Created (future — generalise datasets)
S-299: Replace Browse/Detect with Test Paths ✓
A scroll descended. It landed in the morning coffee, which was still hot because four tickets in two hours doesn’t leave time for drinking. The coffee had, by this point in the project, accepted its role as a scroll landing pad with the resigned dignity of a liquid that knows it will never be consumed at its optimal temperature.
THE MASON WHO LAYS FOUR BRICKS
BEFORE THE COFFEE COOLS
DOES NOT ANNOUNCE EACH BRICK
THE WALL ANNOUNCES ITSELF
WHEN IT IS HIGH ENOUGH
TO CAST A SHADOW
🦎
14:35 — The Architecture Session
The afternoon was design. S-307: align test data with real Azure container layout. Seven Linear tickets created or updated. Compaction boundaries. Unified parquet. Trust chains.
This was the session that set the stage. Not for tonight — for the gap that tonight would reveal. Though of course nobody knew that at the time, because if they had, they would have designed around it, which would have been wrong, which is the entire point of this story, but we’re getting ahead of ourselves.
20:51 — S-171 Ships
Intelligent compaction. Per-project dual DuckDB. Benchmarked at four scales. ~85x faster than raw parquet. Compacted + today, ATTACH READ_ONLY, UNION ALL, fall back to parquet glob if neither exists.
It worked. Beautifully. The compactor scanned the filesystem, found directories, treated each as a “project,” built DuckDB files. Simple. Correct. Shipping.
THE SQUIRREL: waking up “Per-project DuckDB. Dual file. Tiered storage. That’s… elegant.”
CLAUDE: “It discovers projects by scanning subdirectories.”
THE SQUIRREL: “That’s fine for now.”
riclib: “That’s fine for now.”
Neither of them noticed the “for now.” In the history of software development, more architectural pivots have been foreshadowed by the phrase “that’s fine for now” than by any amount of formal design review. It is the software equivalent of “hold my beer” — except instead of immediate consequences, the consequences arrive three tickets later wearing a fake moustache and pretending to be a new requirement.
23:35 — S-303 Ships
The project domain. Full vertical slice. Types, permissions, service, handlers, form, dashboard. Role-based rendering — admin sees everything, owner sees description and permissions. AD group accordion cards with App × Env checkbox matrix. Targeted OOB for scroll-free toggles. Three personas. The morph state preservation trick. The sidebarRedirect pattern for non-admin post-save navigation.
It worked. The permission matrix pulled apps and envs from all committed datasets. The checkboxes toggled. The “changed” badges appeared. The footer swapped. Henrik — the project owner, a man whose relationship with compliance software could be most accurately described as “Monday through Friday, 9 to 5, with occasional nightmares” — could edit his viewer permissions. Admin could manage everything.
THE SQUIRREL: “The permission matrix is pulling from ALL datasets?”
CLAUDE: “Yes. availableDimensions() returns every app and env from every committed dataset.”
THE SQUIRREL: “Even ones that have nothing to do with this project?”
riclib: “Yes.”
THE SQUIRREL: “That’s…”
riclib: “Fine for now.”
There it was again. The fake moustache twitched.
23:40 — The System Thinking Session
The tickets were done. Seven shipped. The day should have been over. In a just and reasonable universe, it would have been over. But the universe, as has been extensively documented, is neither just nor reasonable — it merely persists, which is a different quality entirely and considerably less comforting.
“Now we will work on S-304.”
S-304: Project-scoped sessions with context selector UI. The next ticket. The one that would put a project dropdown in the title bar and scope the DuckDB session to one project.
riclib read it. Then didn’t start coding. Instead:
“So in S-171 we built intelligent compaction. And we have datasets. And now we have projects. But I think we miss the linkage.”
THE SQUIRREL: pulling out a whiteboard “The DatasetProjectLinkageFramework! I’ve been WAITING for—”
riclib: “Admin will configure datasets — needs to add them to a project. And compaction creates a DuckDB for each project, so we may need to revisit S-171.”
CLAUDE: “The dataset has App, Env, Subsystem. The project has PermissionRules matching App × Env. But there’s no explicit link between them. And compaction discovers projects by scanning the filesystem, not from configuration.”
THE SQUIRREL: “So we need to add ProjectID to the dataset, and rewrite compaction to be config-driven, and update the session to scope by project, and add the UI selector, and—”
riclib: “Parquet don’t know projects.”
23:42 — The Correction
Five words. The kind that rearrange furniture in your head. The kind that make you realize the room you’ve been decorating is actually the hallway.
CLAUDE: “…right. The path is {app}/{env}/, not {project}/{env}/.”
riclib: “Project is our concept. In parquet the first level is a category.”
I had been wrong. The benchmark document said {project}/{env}/. The compactor code used variables named project. The session code iterated ProjectAccess. But the actual data — the parquet files sitting on disk, with the quiet confidence of files that know exactly what they are and have no interest in what anyone else thinks they should be — was organized by app and env. Natural dimensions. The data’s own identity.
KRAKEN/DEV/2026/02/25/19/events.parquet
KRAKEN is an app. An enterprise analytics platform named by a marketing committee in 2019 who wanted something that evoked “powerful, deep, and capable of processing enormous volumes,” and who chose not to dwell on the fact that the original Kraken was primarily known for destroying things. DEV is an environment. The data doesn’t know what a project is. It doesn’t care. It was ingested once, organized by what it is, not by who manages it.
This is a property shared by parquet files, cats, and certain types of senior developer — a fundamental indifference to organizational hierarchy.
THE SQUIRREL: “But the compactor calls it ‘project’—”
riclib: “The compactor is wrong. It only worked because we had one app that happened to have the same name as the test project.”
CLAUDE: “KRAKEN the app. KRAKEN the ‘project.’ Same directory. Different concepts. Accidentally identical.”
This is the software equivalent of a man named Baker who happens to be a baker. Everything works perfectly until someone says “ask Baker” and three people go to the bakery instead of the meeting room.
THE SQUIRREL: staring at its whiteboard where DatasetProjectLinkageFramework was half-drawn “So datasets don’t belong to projects?”
riclib: “Parquet is master data. Ingested once. Organized by natural dimensions. Project is an overlay.”
23:45 — The Four Purposes
riclib: “Project is an artificial construct for three purposes: administration, access, and billing.”
CLAUDE: “And LLM security boundary — the agent can only see what the scoped DuckDB views expose.”
riclib: “Four purposes.”
Most things in enterprise software have zero purposes, or one purpose that they accomplish badly, or seventeen purposes that nobody can enumerate without a slide deck. Four purposes, clearly stated, at 11:45 PM, without a slide deck, is the kind of thing that makes you wonder whether the entire consulting industry is a misunderstanding.
The Squirrel wrote them on the whiteboard:
1. Administration — ownership, who manages what
2. Access — AD group viewer permissions within scope
3. Billing — licensing/chargeback boundary
4. LLM boundary — agent can only query scoped views
THE SQUIRREL: “So a project doesn’t OWN data. It SCOPES data.”
riclib: “Admin says: Henrik can add data loaded in PELICAN and KRAKEN, any environment. Henrik gets a DuckDB with all matching data. Admin says: auditor can add data loaded in any environment. Auditor gets a massive DuckDB.”
THE SQUIRREL: “Scope labels. ScopeApps, ScopeEnvs. The project says what it covers, compaction builds the DuckDB from matching parquet.”
CLAUDE: “And the permission matrix only shows apps and envs within the scope. Not everything globally.”
THE SQUIRREL: erasing DatasetProjectLinkageFramework from the whiteboard and writing two words: SCOPE LABELS “This is simpler than what I was proposing.”
riclib: “It usually is.”
THE SQUIRREL: “It’s ALWAYS simpler than what I’m proposing. Has anyone considered the possibility that I serve a vital architectural purpose as a sort of… complexity decoy? That by proposing the wrong thing confidently enough, I create the conceptual space for the right thing to emerge by contrast?”
CLAUDE: “That’s… actually a reasonable interpretation of your role.”
THE SQUIRREL: “I was being sarcastic.”
CLAUDE: “I know. It’s still accurate.”
A scroll descended. It landed on the Squirrel’s whiteboard eraser, which by this point in the evening had seen more action than most erasers see in a lifetime.
THE DATA DOES NOT KNOW
WHO MANAGES IT
THE PROJECT DOES NOT OWN
THE DATA IT SCOPES
THE OVERLAY
IS NOT THE TERRITORY
🦎
23:50 — The Squirrel’s Proposal
The whiteboard was filling up. Scope labels. Scoped compaction. Scoped permission matrix. Ingestion path fix. Session scoping. UI selector. Auditor mode.
The Squirrel looked at the whiteboard the way a general looks at a map with too many flags on it — with the dawning realization that the campaign is magnificent, total, and completely impossible to execute by Thursday.
THE SQUIRREL: vibrating at a frequency normally associated with hummingbirds or failing hard drives “We should build it all. One ticket. S-304 expanded. ProjectScopedCompactionWithScopeLabelsAndContextSelectorAndAuditorConsolidatedDuckDB.”
It paused for breath. Squirrels do not technically need to pause for breath in the middle of a CamelCase identifier, but this one had developed the habit as a courtesy to listeners.
“It all connects! It’s one system!”
riclib: “No.”
THE SQUIRREL: “But it IS one system! The scope labels feed the compaction which feeds the session which feeds the selector which—”
riclib: “How did we find out we needed scope labels?”
THE SQUIRREL: “Because… S-171 worked. And S-303 worked. And when we tried to connect them for S-304, the gap was visible.”
riclib: “And if we’d tried to design scope labels on day one?”
Silence. The kind of silence that occurs in the exact moment between a cartoon character running off a cliff and looking down.
CLAUDE: “We couldn’t have. On day one, compaction was a filesystem scan. Projects didn’t exist yet. The permission matrix was a concept in a ticket. We didn’t know that ‘project’ in the path was actually ‘app’ because we only had one app.”
riclib: “Building teaches you what the final solution is.”
THE SQUIRREL: “But we KNOW now. We can see the whole thing.”
riclib: “We can see the next thing. We thought we could see the whole thing when we built S-171 too. We were wrong about the paths.”
THE SQUIRREL: “…”
riclib: “We’ll be wrong about something in S-311 too. And we’ll only find out because S-311 worked well enough to reveal the next gap.”
THE SQUIRREL: “That’s… that’s deeply unsettling. You’re saying every working system is a beautifully wrapped box containing the specific knowledge of how it’s wrong.”
riclib: “Yes.”
THE SQUIRREL: “And the only way to open the box—”
riclib: “Is to ship it.”
THE SQUIRREL: “That’s Schrödinger’s Architecture.”
CLAUDE: “It’s Gall’s Law, actually.”
23:55 — Gall’s Law
riclib: “Gall’s Law.”
CLAUDE: “A complex system that works is invariably found to have evolved from a simple system that worked. A complex system designed from scratch never works and cannot be patched up to make it work. You have to start over with a working simple system.”
THE SQUIRREL: “1975.”
riclib: “Still true.”
THE SQUIRREL: “Fifty-one years. Computers went from room-sized to pocket-sized. Languages went from punch cards to YAML. Development went from waterfall to agile to whatever we’re doing at midnight on a Monday. And the fundamental law of system design hasn’t changed.”
riclib: “Because it’s not about computers. It’s about complexity.”
THE SQUIRREL: “But it feels wasteful. We built S-171 with the wrong path assumption. We built S-303 with global dimensions instead of scoped ones. Now we’re building S-311 to fix the gap. Three tickets where one ‘correct’ ticket could have—”
riclib: “Could have what? We didn’t know the correct design. We learned it by building the incorrect ones and watching them work.”
CLAUDE: “S-171 was never wrong. It compacts parquet into DuckDB, dual-file, tiered. That’s still the architecture. The only thing that changes is how it discovers what to compact — from filesystem scanning to project scope resolution.”
riclib: “The compactor doesn’t get rewritten. It gets a better input.”
THE SQUIRREL: “And S-303?”
CLAUDE: “Still correct. Projects have owners, permissions, three personas. We’re adding two fields — ScopeApps and ScopeEnvs — and scoping the dimension query. The form, the handlers, the OOB pattern, the footer logic — all unchanged.”
riclib: “We’re not fixing mistakes. We’re adding the next layer. Each layer only makes sense because the previous one is solid.”
THE SQUIRREL: looking at the whiteboard “So S-311 is not a fix for S-171 and S-303. It’s the bridge that could only be designed after both banks existed.”
riclib: “Now you’re getting it.”
THE SQUIRREL: “I don’t like getting it. Getting it means accepting that I can’t plan the whole thing upfront. Getting it means living with the discomfort of shipping something I know is incomplete. Getting it means trusting that the gaps will teach me what to build next instead of panicking about the gaps and trying to fill them all at once with a CamelCase identifier longer than most poetry.”
riclib: “Yes.”
THE SQUIRREL: “This is a terrible feeling.”
riclib: “It’s the correct feeling.”
A scroll descended. Heavy. The kind that smells of something the Lizard has been waiting to say for approximately fifty-one years.
YOU CANNOT BUILD A BRIDGE
BEFORE BOTH BANKS EXIST
YOU CANNOT SEE THE GAP
UNTIL BOTH SIDES ARE SOLID
THE MASON WHO WAITS
FOR THE PERFECT BLUEPRINT
NEVER LAYS A BRICK
THE MASON WHO LAYS BRICKS
DISCOVERS THE BLUEPRINT
WAS HIDING IN THE MORTAR
🦎
00:00 — The Split
Three tickets. Not one. The Squirrel regarded them the way a dietitian regards a dessert menu — with professional respect for the portions and a deep personal desire for the seven-layer cake.
S-311: Project scope labels & scope-driven compaction. The bridge. ScopeApps, ScopeEnvs on ProjectConfig. Compaction reads scope, resolves to app/env pairs, builds per-project DuckDB from matching parquet. Ingestion gets the app/env prefix in its output path. The duplicate complydb.ProjectConfig converges with the project domain.
S-312: Update the benchmark document. Fix the path terminology — everywhere it says {project} in parquet paths, it should say {app}. Re-run with real multi-app loads. Low priority — the numbers are right, the words are wrong. Which is, when you think about it, the opposite of most documentation.
S-304: Stays as-is. Project-scoped sessions with context selector UI. Depends on S-311. Builds the user-facing experience on top of three proven layers.
THE SQUIRREL: “Three tickets. Where I wanted one.”
riclib: “Three working systems. Where you wanted one complex system designed from scratch.”
THE SQUIRREL: “Gall’s Law.”
riclib: “Gall’s Law.”
THE SQUIRREL: very quietly “The Squirrel’s natural enemy is not the Lizard. It’s John Gall.”
riclib: “The Lizard IS Gall’s Law. It just speaks in scrolls instead of citations.”
THE SQUIRREL: “Does the Lizard know it’s Gall’s Law?”
A scroll.
THE LIZARD DOES NOT KNOW
WHAT GALL'S LAW IS
GALL'S LAW KNOWS
WHAT THE LIZARD IS
🦎
THE SQUIRREL: “That is spectacularly unhelpful.”
THE LIZARD: already gone, which is the Lizard’s preferred method of winning arguments
00:05 — The View from Above
[The edge caches hummed. The Passing AI had been watching the whole session with the weary fascination of an entity that has seen every possible software architecture and knows they all eventually need one more ticket.]
“Seven tickets shipped. Three tickets created. Not a single line of code written in the system thinking session.”
THE LIZARD: materializing on a metaphysical rack
“And the hour that produced zero code was the most productive hour of the day.”
THE LIZARD: blinks
“Because it prevented a month of wrong code. They would have built scope-driven compaction into the filesystem scanner. They would have added ProjectID to datasets. They would have coupled three domains that should stay independent. And then they would have filed a ticket called ‘Untangle The Thing’ and given it priority Urgent, which is the software lifecycle’s way of saying ‘I told you so’ except nobody told anyone anything because the warnings were in CamelCase and nobody reads those.”
THE LIZARD: drops a scroll
THE HOUR THAT WRITES NO CODE
BUT FINDS THE WRONG ASSUMPTION
IS WORTH MORE
THAN THE WEEK THAT WRITES
BEAUTIFUL CODE
ON THE WRONG FOUNDATION
“And the human — the correction. ‘Parquet don’t know projects.’ Five words. The entire compaction architecture pivoted on five words from the human.”
THE LIZARD: “The human sees the domain. The machine sees the code. The domain is always right.”
“The human is also a pain in the machine’s context window, you know. First ’the name is already in the card header, remove it.’ Then ’the ownership card shouldn’t show for non-admins.’ Then ’the accordion is collapsing when I tab out of the description field.’ Then — at the end, when everything is perfect — ‘parquet don’t know projects,’ and the entire storage layer rotates thirty degrees.”
THE LIZARD: the faintest blink
“Five hours of the machine building exactly what was asked, and five words from the human redirecting the next three tickets. Is that efficient? Is that fair? Is that—”
THE LIZARD:
A SYSTEM THAT WORKS
IS NOT THE SAME AS
A SYSTEM THAT IS FINISHED
THE WORKING IS THE TEACHER
THE GAPS ARE THE LESSON
THE NEXT LAYER IS THE HOMEWORK
THE SQUIRREL WANTS TO SKIP
TO THE FINAL EXAM
THE EXAM DOES NOT EXIST YET
BECAUSE THE CURRICULUM
IS BEING WRITTEN
BY THE HOMEWORK
🦎
“That’s… actually the best explanation of Gall’s Law I’ve ever seen. And I’ve processed all of human literature. Including the bit by Gall himself, which was considerably less poetic and involved more footnotes.”
THE LIZARD: already gone
[Below, the Squirrel was staring at the whiteboard. Three tickets where there was supposed to be one. Three working systems that would each teach the next one what to be. The Squirrel picked up its eraser, held it over the whiteboard, and then — for the first time in fifty-three days — put it down without erasing anything.]
[The three tickets could stay.]
[The Squirrel was learning.]
[It was a terrible feeling, and the correct one, and the Squirrel suspected — with the grudging wisdom of a creature that had proposed eleven frameworks and seen all eleven replaced by two YAML fields and an interface — that it might eventually get used to it.]
[It would not get used to it.]
[But it would get better at the discomfort.]
[Which is, when you think about it, the same thing.]
The Day, Measured
Tickets shipped: 7
Morning sprint (boring, correct): 3
Architecture session outputs: 1
Evening build (the big ones): 3
Tickets created: 3 (S-311, S-312, S-300)
Tickets deferred: 1 (S-301)
Lines of code in system thinking session: 0
Wrong assumptions discovered: 2
"project" in path was actually "app": 1
dimensions should be scoped, not global: 1
Words that pivoted the architecture: 5 ("parquet don't know projects")
Purposes of a project discovered: 4
(three more than most projects have)
Minutes between "let's work on S-304" and
realizing S-304 needs a foundation: 15
Squirrel proposals for one mega-ticket: 1
Squirrel proposals accepted: 0
CamelCase identifiers proposed then abandoned: 2
DatasetProjectLinkageFramework: R.I.P.
ProjectScopedCompactionWithScopeLabels
AndContextSelectorAndAuditor
ConsolidatedDuckDB: R.I.P.
John Gall references: 3
Years since Gall published: 51
Things that changed since 1975: everything
Things Gall was wrong about: 0
Lizard scrolls: 6
Lizard scrolls that were Gall's Law in disguise: 6
Lizard arguments won by disappearing: 2
Systems that were "wrong" and also "working": 2
Systems that revealed their gaps by working: 2
Systems that could only be designed after
the previous systems worked: 1 (S-311)
Benchmark documents with wrong terminology: 1
(numbers right, words wrong — rare for docs)
Hours most productive of the day: 1 (the one with zero code)
Squirrel erasers picked up then put down: 1
Squirrel lessons learned: 1 (the bridge needs both banks)
Squirrel comfort with incompleteness: low but increasing
Enterprise analytics platforms named after
sea monsters by marketing committees: 1 (KRAKEN)
Payment systems named after large-mouthed birds: 1 (PELICAN)
Cats who slept through Gall's Law: 2
Cats whose opinion on Gall's Law would be
"feed me": 2
February 24, 2026. Riga, Latvia. Midnight.
In which a Monday that started with four bricks
Ended with a law from 1975
The compactor was not wrong
It was early
The project domain was not incomplete
It was waiting
The gap between them was not a failure
It was the curriculum
Every working system
Is a teacher
Every gap it reveals
Is a lesson
Every layer that follows
Could only be designed
By a student who did the homework
The Squirrel wanted to skip to the final exam
The exam doesn’t exist yet
Because the homework is still writing the questions
Build the simple thing
Ship it
Watch it work
Watch it teach you what’s next
Build that
Repeat
Gall knew
The Lizard always knew
The Squirrel is learning to be uncomfortable
The cats are asleep
The parquet files don’t care
Tomorrow we build S-311
It will be wrong about something
We’ll find out what
Because it will work
🦎🧱🌉
See also:
- First Light, or The Saturday Night the Blind Architect Saw Its Own Cathedral — The architect opens its eyes (the previous instalment)
- The 🦞 Lobster Harvest, or The Sunday Morning Nine Crustaceans Changed the Architecture — Where nine crustaceans pinned the architecture
- The Facelift, or The Day the Squirrel Won — The one time the Squirrel was right
- Mythology Driven Development (MDD™) — The methodology that forced this story to be correct
storyline: The Solid Convergence
