Sam Zoloth

Builder's log

What I built, tried and cut, as it happened

These are field notes from my side projects, newest first. Each one starts from the commits and pull requests behind a change, and I edit it before it goes up. The lab holds the directions the homepage took.

26 days, Sep 15 to Oct 10

16 entries

October 2026

2026#016

BeaconUpdate

Beacon got faster and started drafting follow-ups

In early October Beacon could import mymind saves from a local CSV export. A command previews the file without opening the database, keeps every original field, and is safe to repeat. Then it grew a Triage app for Mac and iPhone with project briefs, and lifestyle areas that a save can be kept into.

Speed came next, with new benchmarks to measure it. Triage used to show nothing for 2 to 2.6 seconds after launch, and up to a minute when the Mac was busy. Now last time's list shows in about 0.75 seconds and the fresh one replaces it shortly after. Choices made while Triage reloads are kept instead of lost.

On October 10, keeping a save on an area such as Travel or Food began to queue a follow-up. A weekly job runs one read-only agent per follow-up. The Briefs tab shows its summary, steps and copyable drafts. Nothing is sent or booked.

PR #2 · 360fe1f · PR #3 · 4b39866 · PR #5 · 96c14ae
2026#015

BeaconDecision

Beacon stopped waiting for me to triage

Beacon collects my saved links and starred repos and asks me to keep, pass, read, or act on each one. Deciding every save by hand was too slow. In 30 days I made 24 of those choices while 398 saves waited.

Now a weekly run acts on Beacon's own suggestion for each queued save. Noise gets passed, up to 45 worth-reading saves go to a read-later inbox, oldest first, and anything suggested as a to-do stays for me. Triage shows five picks instead of the whole queue. Every choice I make is stored next to the suggestion I saw, and an undo counts as Beacon getting it wrong, so its accuracy can be measured later without a labeling pass. The database was backed up and the run went dry first, with a spot check of what it passed. The first real run passed 128 saves and sent 15 to read later.

PR #10 · de0cc62
2026#014

BrailleUpdate

Braille gets tables, citations and journals by voice

On October 9 and 10 Braille picked up a batch of features. It reads tables exactly and answers row and value requests by voice. It lists related papers, papers that cite the open one, and its references. It can follow journals, compare two papers, and trace a concept by voice. Hands-free listening gained lock screen controls, a speed setting, Siri and on-device answers.

Two changes prepare it for other listeners. Listeners now bring their own OpenAI key, and the app builds for iPhone only so App Store uploads validate. The last fix moved the speech analyzer's microphone tap off the main actor.

PR #81 · cdcd62e · e4cd56f · PR #83 · 216ff01 · 425de67
2026#013

KindredUpdate

Kindred gets a privacy manifest and a policy page

Build 6 of Kindred puts a privacy manifest on every target in the app, and sent push notifications are deleted after a day. The export options file now lives in the repo. The app also has a privacy policy page on this site.

Kindred's Groceries list with items checked off by two people.
Kindred's To-do list with chores due and who is on them.
9778c10 · 7890c6e · d7fb174
2026#012

NotebookUpdate

Relationship Notebook pulls in my data and syncs across devices

The notebook's source went into its own repo on October 8, with a prioritized roadmap. By October 10 it had filled up with my own data. It syncs Contacts, Messages and Calendar into each person's story, then Gmail, LinkedIn and Instagram exports with background syncing.

Every person got a pixel-art character. It is made from their Contacts or Apple Photos picture when there is one, and a gray mystery figure when there isn't. Companies get a storefront. The app also gained a Today home and duplicate handling.

Later on October 10 the notebook moved into the app's private iCloud container, so the Mac and iPhone share one copy. Reads and writes go through Apple's file coordinator. When both devices saved while apart, the copies merge person by person and the newer edit wins. Deleted people leave a marker, so a stale copy can't bring them back.

The Mac People list before characters, with initials in circles and a plain row for each person.The Mac People page after, a grid of pixel-art characters with sample names.BeforeAfter
5b500bc · 4386b30 · e4392c8 · PR #2 · 9bd11ba · 2e0e240
2026#011

NotebookCut

Work sorting lasted a day

Relationship Notebook suggests people from my contacts, messages, calendar, and mail. On October 9 it got automatic Work sorting. Anyone at a company domain started in Work, and a Personal/Work picker filtered the list. Later that day a Leave out setting arrived. It skips anyone at the listed domains, and any meeting they're in, everywhere in the app. On my Mac, calendar entries dropped from 6,574 to 55.

The next day the picker was deleted. Every page shows everyone, and new people start as Personal.

475f8d3 · 249d2ec · PR #9
2026#010

BrailleCut

Deferred PDF import for a publisher sign-in sheet

Most new papers are abstract-only in PubMed Central. Of the 30 newest on my design partner's topics, 10 were in PMC, 10 were free elsewhere, and 10 were paywalled. There were two ways to close that gap. Braille could parse PDFs opened from Mail or Files, or it could open the publisher's page and let the listener sign in with their own access.

I shipped the publisher page and put PDF import on the backlog. The estimate was two to three days, and the hard part is turning two-column layouts, running headers, and hyphenation into clean paragraphs in source order. An extracted page becomes a paper only if it clears a quality check of at least 5 paragraphs, 6,000 characters of body text, and a title matching 60% of the PubMed title's words. Teaser pages are refused with a spoken reason. When a publisher shows a "verify you are human" check, Braille waits for a person and does not try to get around it.

PR #82 · c58f083 · 3ce18d2
2026#009

NotebookTried

Let the on-device model judge whose turn it is

The notebook's Replies page answers one question per thread. Do I owe a reply, am I waiting, or is nothing pending? I moved that call to Apple's on-device model. It reads the last few messages and says what the last one does, and code turns that into owed, waiting, or nothing. Only the verdict is stored. Without Apple Intelligence it falls back to whoever wrote last.

I tuned it against 40 made-up threads, which took it from 60% to 95%. Then it scored 85% on 20 fresh ones before anything else changed. On my own Mac, 16 of 29 open threads turned out to need nothing. Replies also became a card stack, one thread at a time, with a tray for threads the check cleared so I can correct it.

PR #6 · 4bf3043 · 079268d · af68a81
2026#008

NotebookCut

Moved the Mac checks off hosted CI

macOS minutes count ten times against the free GitHub Actions quota on private repos, and the notebook's UI tests used about 14 of them per run. The UI tests had gone green in hosted CI. I still cut them back in two steps on the same day. First, UI tests ran only on manual dispatch and duplicate branch-plus-PR runs stopped. Then the Mac and iPhone app builds went on demand too.

Before merging, a local script now runs the core tests, an agent smoke test, and both app builds. Only the Linux core tests run automatically.

1090212 · 3afe636 · cb38cc9
2026#007

NotebookDecision

Rebuilt the notebook after listing how it lost data

Relationship Notebook is my personal CRM. Before rebuilding it, I listed how the prototype failed. An unreadable store was silently replaced with demo data and overwritten. On Mac, the note editor carried one person's text into the next person. The app and the agent CLI each wrote the whole file and never reloaded, so the last writer won. Dates were display strings like "Just now".

The rebuild sits on a tested Swift core. One versioned file holds people, agent history, proposals, and the import ledger, and every write is a locked read, modify, and write with an atomic save. The agent CLI proposes by default and needs an explicit flag to apply a change. The rebuild had a bug of its own. Retrying an apply checked for staleness first and failed before it reached the idempotency check, so the fix checks for a prior application first.

PR #1 · 4cc4333 · 46f6747
2026#006

BrailleDesign revision

Ten buttons down to one sentence and a dock

The Braille reader screen was a column of ten system buttons and status lines. I rebuilt it around the sentence being read. That sentence is one large serif line in focus, with a single dock for previous, play or pause, and next. Source rights, saved position, and start over moved into a pull-up tray. Play now reads continuously, and any tap on screen cancels a pending spoken answer.

The design bar was Benji Taylor's Family Values principles of simplicity, fluidity, and delight. Review caught two things to cut. Haptics would have fired on every sentence, and a late answer could override a tap. A single-sentence action went too, because continuous play left it unused. Every size follows Dynamic Type, and a follow-up fixed the layout at the largest text sizes.

The Braille reader screen, one large serif sentence in focus above a dock with previous, play or pause, and next.
PR #80 · 63a8c9f · a835663
2026#005

KindredDesign revision

Three app icons in one day

Kindred is a small iPhone app for couples, with shared lists, calendars, and chores. On October 9 it went through three icons. The first was a magnifying glass, after the app's detective-themed working name. Two overlapping circles came with the rename to Kindred. The third is a note pinned to a green fridge door, ticked in two people's colors.

For the last round I compared four directions on one page, each on a light and a dark home screen. The brief was no blue and pink, nothing that looks like a logo, and it has to work for any two people. The fridge note won, on the idea that the fridge door was every home's first shared list and calendar. The rename kept the bundle ID and iCloud container, so existing installs and data carried over.

16b23ba · 51c44f4 · 4d0616b
2026#004

BeaconDecision

Two apps were syncing the same saves

Beacon and Mosaic, a Mac reference library, both synced my X bookmarks and GitHub stars. The first goal in the plan was to stop maintaining the same thing twice. I ordered the work so the early phases stand on their own if the later ones stall. First Beacon took over fetching, and Mosaic switched to reading Beacon's library feed, which deleted Mosaic's own X and GitHub connectors and sign-in flow. Then I built one new app for Mac and iPhone with Triage, Library, and Briefs, and moved the library features in. Those are search by words and by meaning, more like this, and adding my own links and pictures.

I mocked three layouts, called Shelves, Deck, and Today, and picked Today. The risk I wrote down was building instead of using, so the test for every phase is whether I triaged or browsed more that week. The old apps stay until the new one covers them.

PR #4 · PR #22 · PR #6 · PR #7
2026#003

This siteDecision

Who pays for the 3D desk

The homepage on this site is a 3D cabinet, and the first build made every visitor pay for it. Every visitor preloaded three.js (264 KB) and the desk model, including people who would only ever see the static poster version. Browsers without a GPU, PageSpeed's test machines among them, drew WebGL on the CPU and held the main thread for about 9 seconds. Compiling every shader before the first frame froze the page for about a second on a mid-range phone.

The fixes put the cost on the visitors who get the live desk. Software-rendered WebGL now gets the static posters. three.js and the model download only when the live desk will run. Shaders compile in parallel, and merging meshes by material took the desk from 365 to 233 draw calls a frame. The posters themselves had never shipped in the build, which left the desk area empty. That was fixed too, and a failed download now falls back to the posters instead of a blank desk.

The static poster of the 3D desk, a cabinet of drawers with a monitor, lamp and a small figure on top.
The static poster
5dcdb57 · 602e98a · 4a671ea · 1ab6726 · c4a48a7
2026#002

BrailleUpdate

Braille learns to find, open and resume papers

The first Braille build read a bundled sample paper aloud on the phone, sentence by sentence, with on-device voice commands and a Siri shortcut to start. The paper was synthetic. Over the next three weeks it learned to work with real ones.

A repair in mid-September stopped interrupted research from landing an old result over the current paper. It also made End session stop the microphone even when the call to cancel failed. A round of end-to-end QA then found and fixed seven problems in the user journey. After that Braille read real PubMed Central papers to the end, and its NCBI lookup accepted the official NLM PubMed DOCTYPE.

By October 5 I could ask for a paper by voice and Braille would find it on PubMed and open it, in a neural voice that no longer talked over itself. I could jump to any section by its title. After a relaunch it came back to the saved position, including for papers opened by search, and a spoken question got the exact sentences from the open paper.

A spoken question, "What was the hazard ratio?", with the answer quoted from the paper's results beside an iPhone running Braille.
PR #63 · PR #66 · ca6b769 · 4730397 · 98a5551 · PR #72

September 2026

2026#001

BrailleDecision

One useful session before any model bakeoff

Braille reads research papers aloud and answers spoken questions about them. By mid-September it had a 108-run model comparison behind it and a ranked list of speech-to-text, turn-taking, and voice candidates. I demoted both to later work and wrote a pilot spec instead. The pilot is one assisted session, on one iPhone, with one paper and one configuration that works. The loop is read, interrupt, ask, hear the exact source sentence, return, and reopen.

The rule I wrote down is that an optimization has to name the observed failure or real cost, the smallest change, the expected improvement, and when to stop. Until the first useful session there is no multi-provider bakeoff, model picker, router, or new evaluation platform. The pilot also has a stop list. A changed number, an answer from the wrong paper, an invented source, or speech that can't be stopped ends it.

300ee2e · a05f05c

Nothing here for that filter yet.