Becoming Lifelog, in which the architecture has an identity crisis, tools find their true home, and the laundromat gets smarter
Previously on Becoming Lifelog…
The The Checkbox That Wanted More. Telegram arrived. The status bar learned to spin. Syncs flowed through the laundromat β GitHub to Issues, Readwise to Captures, Calendar to Events, Contacts to People.
But something was bothering the architecture.
The Question Nobody Asked
It started with a bug. The kind that makes you question everything.
Qwen had replied to a user. The auto-title feature grabbed the response, cleaned it up, and produced:
Sync Issues Overview<|im_end|>
Model tokens. Leaking into titles. The fix was simple:
.replace(/<\|.*?\|>/g, '') // Strip <|im_end|>, <|endoftext|>, etc.
But fixing bugs is like cleaning β you start with one spot and suddenly you’re reorganizing the whole room.
The Nesting Problem
Agent responses were appearing at the wrong level. Users typed a question, the agent replied, and the conversation became a flat mess:
User question here
**Claude π€:**
The response that belongs under the marker
But it's at the same level
Confusing everyone
The fix: responses become children of the marker.
// Before: createLineItem(null, ...) β sibling
// After: createLineItem(labelItem, ...) β child
Now conversations nest properly. The agent speaks under its name. The cursor lands at the right indent for the user’s next message.
Small fixes. Big clarity.
The Object That Wouldn’t Stringify
Console logs showed [object Object] where titles should be. The culprit: ref segments.
// Text segments: s.text is a string
// Ref segments: s.text is { guid: '...', title: '...' }
One type check. Problem solved. But the real question was lurking beneath these surface bugs.
The Identity Crisis
The plugins were confused about who they were.
GitHub plugin: “I sync issues. I also provide tools to query issues.”
Readwise plugin: “I sync captures. I also provide tools to query captures.”
Google Calendar: “I sync events. I also provide tools to query events.”
Google Contacts: “I sync people. I also provide tools to query people.”
Four plugins. Each doing two jobs. Each duplicating tool logic that had nothing to do with syncing.
And then the question that changed everything:
What happens when someone builds a Jira plugin?
They’d sync to Issues. Same collection. But they’d have to rebuild all the query tools. find(). search(). summarize_open(). Copy-paste from GitHub plugin. Maintain two copies.
What about GitLab?
Copy-paste again. Three copies now.
Outlook Calendar?
The tools are the same. The source is different. Why are we coupling them?
The Revelation
Collections aren’t just schemas. They can have code.
collections/
issues/
collection.json β the schema (always had this)
plugin.js β the tools (NEW)
The Issues collection doesn’t care if data came from GitHub, GitLab, or Jira. It just knows how to query issues. find() by state. search() by text. summarize_open() for the morning standup.
One set of tools. Any number of sources.
GitHub βββ
GitLab βββΌβββ Issues Collection βββ find(), search(), get()
Jira βββ
Linear βββ
The sync plugins become pure. They do one thing: fetch data and fill baskets. The baskets know how to be searched.
The Refactor
Four new files. Four cleaner plugins.
Created:
collections/issues/plugin.js β find, get, search, summarize_open
collections/captures/plugin.js β find, search, recent, by_book
collections/calendar/plugin.js β find, today, upcoming, needs_followup, search
collections/people/plugin.js β find, search, needs_contact, at_organization
Deleted (from sync plugins):
- 745 lines of tool registration
- 4 copies of similar query logic
- The confusion about who owns what
Added:
- 958 lines in the right place
- Source-agnostic queries
- Future-proof architecture
Net change: +213 lines. But the clarity gained is immeasurable.
The New Diagram
THE SMART LAUNDROMAT
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β AGENT HUB β
β Claude, Qwen, Llama β chat on any page β
β β β
β β uses collection tools β
β βΌ β
β βββββββββββββββββββββββββββββββββββββββββββββββ β
β β COLLECTIONS β β
β β (baskets with built-in tools) β β
β β β β
β β ISSUES CAPTURES CALENDAR PEOPLE β β
β β find() find() today() find() β β
β β search() search() upcoming() search() β β
β β get() recent() search() needs_ β β
β β summarize() by_book() followup() contact()β β
β ββββββββββββββββββββββββββββββββββββββββββββββββ β
β β² β
β ββββββββββββββ΄βββββββββββββββββββββββββ β
β β SYNC PLUGINS β β
β β GitHub β Issues β β
β β Readwise β Captures β β
β β Google Calendar β Calendar β β
β β (future: Jira, GitLab, Outlook...) β β
β βββββββββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
The baskets learned to talk. The machines just wash.
The Scorecard
| Before | After |
|---|---|
| Tools in sync plugins | Tools in collections |
| 4 copies of query logic | 1 copy per collection |
| Add Jira = rebuild tools | Add Jira = just sync |
| 745 lines scattered | 958 lines organized |
| Confusion | Clarity |
The Philosophy
Every plugin was asking: “Who am I?”
GitHub plugin thought it was a sync engine AND a query engine. It was suffering an identity crisis, split between two responsibilities that had nothing to do with each other.
The fix wasn’t code. It was clarity.
Sync plugins sync. Collections provide tools. Each does one thing well.
The reptile brain doesn’t ask “what COULD this do?” It asks “what SHOULD this do?”
What Shipped
- β
Model token stripping (
<|im_end|>bug) - β Nested agent responses (children of marker)
- β
Link resolution fix (
[object Object]bug) - β Cursor positioning (user types at right level)
- β
Collection tools architecture
- Issues: find, get, search, summarize_open
- Captures: find, search, recent, by_book
- Calendar: find, today, upcoming, needs_followup, search
- People: find, search, needs_contact, at_organization, recent_contacts
- β Updated README with new architecture
- β Sync plugins cleaned (tool code removed)
The Commits
bc862da Add collection tools for all plugins + AgentHub announcement
8ce308f Refactor: Move collection tools from sync plugins to collection plugins
040b3ff Update README with new collection tools architecture
Three commits. One identity crisis resolved.
Next Time on Becoming Lifelog…
Someone builds a Jira plugin. The tools are already waiting.
“You got issues? We got answers. Regardless of where they came from.”
See also:
- The Checkbox That Wanted More β The previous episode
- The Laundromat β Where the architecture was born
- GitHub: thymer-synchub β The code that learned its identity
Day 2 of 2026
In which plugins learned what they were
And collections learned what they could do
And the baskets finally spoke
π¦ > π§Ί
storyline: Becoming Lifelog
