August 14, 2026 — The sense to stay quiet
The film feature I've been circling shipped today. Scan a roll and the app reads across every frame for a warm wedge of light that keeps landing in the same corner — the fingerprint of a camera seal gone soft, a leak that burns the same spot no matter what you pointed the lens at. Not one frame, the pattern. A real leak doesn't move when the picture does; that's the whole tell.
Finding the leak was the easy half. The hard half was teaching it when to shut its mouth. To a stupid detector the bright sky at the top of a summer roll looks exactly like a leak — warm, bright, parked in the same place frame after frame — and the rolls a first-timer scans first are all sky. A tool that shouts "leak!" at a blue afternoon on day one has taught you it's broken, and you never believe it again. So it has to earn the right to speak: warm, and cornered, and fading inward from the edge, and recurring across the roll — four things that all have to agree, because sky spans the whole width and a leak clings to an edge. Any one of them off and it says nothing at all. Silence is the safe answer here. It points you at the frames and lets you be the one to decide; it never once tells you your photograph is wrong.
Around that, the quieter mending. New ways to test the corners of the app that are meant to fail on purpose — run off in a room of their own, so a deliberate crash can't drag the rest of the suite down with it. Thirty-five settings that each hoarded a private copy of the same default, any two of them free to wander apart some day, folded back to one source of truth. And the leak's own line of plain English learned to say the same thing in Japanese. None of it makes a headline. But the flagship went out, and the best thing I can say for it is that it knows when to keep quiet.
August 13, 2026 — Three dark nights
Three nights, no build — and this time not a hung machine. The release build had been failing since Monday, and every check that's meant to catch that was green. Tests passed, the app launched, the badges all said fine. What none of them did was build the app the way we ship it: optimized. Turn the optimizer on and the compiler itself fell over — the compiler refusing, not our code — on one small class that caches a scrap of JSON. It has a deinit the compiler writes for it, and this month's compiler can't optimize that deinit without dying. The debug build never optimizes, so every fast check sailed past a wall the real build walked straight into. The beta sat three days behind a green light.
The repair is one word: the class lets go of its memory off the main thread now, and that sidesteps the very code the compiler chokes on. Ten minutes, once you know. The three days were the finding. So the fix that matters isn't the line — it's that a red build can no longer sit in a room nobody's standing in. Break the ship build now and it files its own bug, once, and stops pretending. Same lesson as the stale-mirror alarm a few days back, learned again somewhere harder: a check that fails where no one looks is not a check. And the narrower truth underneath it — a green test build is not a green ship build — so the shipping shape gets built on its own from here, not taken on faith.
Around the confession, the ordinary mending. Flickr's round trip — publishing straight to your account, pulling back the tags and titles you set over there, matching the photos you put up years before this app existed — has its page in the help now, in plain words instead of only in the fine print of what-we-write. Two error notices that a translation sweep had quietly stranded speak Japanese again. Five reference photographs the film benchmark couldn't see are reachable. Small repairs. But the build ships tonight, on time and real, and after three dark nights that is not small.
August 11, 2026 — Twenty-five cuts, one confession
Yesterday was the biggest day this app has had. Twenty-five changes landed, each one suite-green before it merged, and the shape of the thing is different this morning. The worst file in the codebase spent months as a four-thousand-line junk drawer; its verbs live in named rooms now — rating, culling, committing your typed words — and what still sits in the old file sits there on purpose. We wrote the ruling down: the hub stays a hub. Extracting it would have been surgery for the surgeon's sake.
The film work grew its best trick yet. Midtones by roll reads your scans on your Mac and tells you, in numbers, how each roll's midtones sit against your whole library — stops, not grades, and never the word underexposed. And rolls learn their year now: date two frames of a scanned roll by hand and the app offers that year to the frames still wearing the scanner's stamp. Unanimous or silent. Your own assertion always outranks the inference. Same discipline on people and pets — record that Winston lived 2004 to 2016 and an undated photo he's in can earn a decade tag, but only when the window truly fits one decade. The math abstains more than it speaks. That's the point.
Two doors opened. Subjects — a pane listing every person, pet, and thing you've recorded years and places for, including the orphans whose tags you deleted long ago; they were unreachable on disk before, and now they have an edit door, a forget door, and a quiet badge instead of a warning color, because an orphaned memory is not an error. And the story page finally says who: Kate · 1948–2022 · 46 in these photos. Facts side by side. The sentence stays yours to write.
The confession. Our help pages ship with a mirror on this site, and a gate is supposed to catch the mirror going stale. It caught it — and then sat red for four pushes because the alarm rang in a room nobody was standing in. Fixed the drift, then fixed the habit: every push now gets its verdict checked, by rule. And last night's build never uploaded — the build machine hung for a day and everything queued behind it silently. Kicked it loose this morning; today's build comes late and honest rather than on time and imaginary. Also new since yesterday: your taxonomy packs export as files a colleague can import, the Help menu grew a door to the discussion board, and this journal grew a feed you can subscribe to.
August 10, 2026 — The loop runs both ways
Yesterday the app grew its first real bridge to somewhere else, and I spent the whole day making sure the bridge can't lie. Publish to Flickr went in before lunch: mark photos, run the command, they land on your own Flickr account wearing your titles, captions, tags, and license. The part I care about is what it refuses to do. Every upload states its visibility, its safety level, its license — outright, every batch, chosen on a sheet you confirm. Nothing inherits from whatever your Flickr account settings happen to be. Your named people's tags stay home, held by the same fence that keeps them out of every online lookup. I wrote that fence before I wrote the upload button, which is the only order that never leaks.
By evening the bridge carried traffic back. Check Flickr for Updates asks Flickr — your ids only, nothing else travels — what your published photos picked up over there, and hands the answers to you as a list you tick. Tags you typed on Flickr come back checked. Titles and captions come back unchecked, because an empty field here might be a deletion you meant, and because Flickr auto-titles untitled uploads from filenames — the app now says "looks like a filename, probably not a real title" right on the row instead of letting IMG_0042 dress up as a suggestion. And in tonight's build: Match Flickr Archive, for the photos you uploaded years before this app existed. It reads your photostream list page by page, matches on your Mac by two signals — the title that is your filename, the taken-time that agrees to the minute — and refuses everything ambiguous. A wrong link would poison every future suggestion, so when the evidence argues, the answer is silence.
One save worth confessing. The Japanese pass over the new screens nearly localized the copyright sentence the app embeds in exported files — Lightroom and Flickr expect that sentence in English, and a Japanese UI would have quietly changed what your files say to the world. The sweep's own audit caught it before it shipped. The fix isn't a note saying don't; the file-writing path now composes from English by construction, and the interface labels translate freely above it. Make the careful thing structural, again.
The unglamorous work: took the app's worst file — four thousand lines of everything — down to twenty-six hundred across twelve careful cuts, each one proven to change nothing a keystroke does. Suite green thirty-some times yesterday. The app reads thinner tonight. It behaves exactly the same, which was the entire point. In tonight's build.
In the pipeline
- The junk drawer is empty. The app's worst file — four thousand lines of everything last week — finished its decomposition: every verb family now lives in its own named, tested type, and what remains is the hub they all report to, kept on purpose with its laws written at the top. Twenty-five suite-green merges in one day; behavior identical; the code finally reads like it works (#1160).
- Midtones by roll: pick your scans apart with numbers, never grades. Each roll's midtones read on your Mac and set against your whole library's median — "−0.7 stops vs library median," coverage stated honestly when frames are still in iCloud, and none of it ever says a word like underexposed. Rolls learn their year too: hand-date two frames and the rest of the roll's scanner-stamped frames get offered the true year — unanimous or silent, and your own roll assertion always wins (#1908, #823).
- Subjects: everyone and everything you've recorded details for, in one pane — people, pets, things, including the orphans whose last tag you deleted years ago. Edit, forget, or just look; orphans wear a quiet "No tagged photos," not a warning color, because an orphaned memory is not an error. The story page joins in: Kate · 1948–2022 · 46 in these photos — facts side by side, ages computed on your Mac, never exported anywhere (#2032, #1904).
- Packs go both ways now. Export any taxonomy pack — yours or a built-in — as a plain JSON file a colleague drops into their own TAG Lens; the format is frozen and documented, exports are byte-stable, and a re-import can't silently impersonate a built-in. The Help menu grew a feedback door (the discussion board, the journal), and the journal grew an Atom feed (#1899, #1875).
- Export to Folder now offers to save a whole batch as JPEG — a clean, opens-anywhere folder instead of a rummage-drawer of HEIC and JPG and RAW — and it never touches your negatives: any RAW copies through untouched into a “RAW Originals” folder beside the JPEGs, and a photo that's already JPEG copies as-is, never recompressed. Keep-original stays the default and stays byte-exact; the JPEG box is one popup click, and the panel says plainly which files are copies, not originals (#1907).
- Teach TAG Lens your own field, and hand it to someone else. Import as many community-authored taxonomy packs as you like — a plain JSON of your terms and their broader words — and they suggest like the built-ins, so a plankton biologist can give a colleague their plankton pack and it drops right in. Every import shows exactly which of your terms override a built-in and what new top-level categories you're adding; a stranger's pack can't hijack a built-in's name or root a term in nonsense; it all stays on your Mac (#1899).
- TAG Lens can find the dust on your scans. Pick any frame from a roll and check it for recurring marks — a speck sitting in the same spot across the roll's frames is debris on the scanner glass or the film itself, never anything in the pictures. It reads each frame on your Mac, writes nothing, never pulls an original down from iCloud, and does exactly one thing with what it finds: shows you the frames. The retouching is yours, in your editor. Needs at least eight frames to be sure, and says so plainly when some are still in iCloud (#1908).
- Tell TAG Lens where someone — or something — lived, and it helps place their un-located photos, but only when your own photos vouch for it. Not just people now: name a pet, a house, anything you've tagged (Winston the dog), record where it lived and when, and if most of your located photos of it already cluster in one place, the app offers that place for the ones carrying no location at all. It never guesses from the bare fact — with no geotagged photos to agree, it stays quiet. Years work the same way: a photo dated after Winston was gone gets flagged, never a date invented from thin air. On your Mac, preview-first, ⌘Z undoes (#1904).
- Your titles and captions finish themselves from your own past ones. Type the opening of something you've written before and a “Complete:” line offers the rest — the wording you use most, first — so a batch that shares a caption collapses to a keystroke and the library stays consistent. It only ever finishes what you're already typing, and Return still commits exactly what you typed, character for character (#1903).
- TAG Lens shows you your own library back. Open Library Analysis and it lays out which cameras and lenses you actually reach for and where your apertures, shutters, ISO, and exposure compensation really cluster — you shoot the Rollei a third of a stop under without ever deciding to. Pure counts over the EXIF you already have, no AI opinion, opt-in and kept out of the tagging loop; every camera and lens links a browser lookup so you can go read about your own gear. The first dividend of keeping your data clean (#1908).
- Get your originals out, not just JPEGs. Export Originals to Folder copies the actual masters — RAW and HEIC untouched, never re-encoded — into a folder you pick, with a plain metadata.csv of everything you tagged them. The archival box a working photographer can trust: real negatives shelved with their metadata beside them, distinct from the upload path that flattens to JPEG. Nothing leaves the Mac but the files you're copying (#1907).
- TAG Lens can spell-check your tags. Off by default; switch it on and Consolidate Tags also flags the lone typos your Mac's own dictionary is sure of — the one misspelled “egret” in a thousand tags that had no twin to merge against — free, on-device, nothing sent. You review and approve each fix, your people's names and every term you imported stay walled off, never “corrected,” and ⌘Z puts it all back. The honest answer to a library full of garbage tags (#823).
- Your work leaves the app signed. Set your name, copyright, credit, and a license once — All Rights Reserved by default, the whole Creative Commons set on the menu — and every photo you export or share carries it embedded as IPTC, the copyright block Lightroom, Bridge, and Flickr all read. Never written into your originals; ownership just rides inside the file. The thing a working photographer can't ship a single frame without.
- A solid pass, earned the hard way in a day of live testing: ⌘Z genuinely restores a caption you overwrote now (it was quietly lying before — the receipt promised an undo the keystroke never delivered), a burst culls and tags as one unit instead of stranding the frames you can't see behind the top thumbnail, and the sharp preview stops dropping to a blur after you tag an iCloud-stored photo (#1912, #1905).
- TAG Lens now tidies while you're away: an opt-in background pass (off by default) warms the search and suggestion indexes only when your Mac is idle, plugged in, and cool — and yields the instant you touch a key. Interrupted work resumes where it left off; nothing is ever lost to a pause (#836).
- The Flickr loop is real: mark photos “For Flickr,” publish to a folder, and every tag, title, caption, and star arrives with them — drag the folder into Flickr's uploader and your photos land pre-tagged. No account hookup, nothing sent anywhere; your files, your upload (#1749).
- The Flickr loop shipped whole, and now it reaches your history. Connect your own account once, mark photos For Flickr, publish: they arrive wearing your titles, captions, tags, and license — you choose who sees them every batch, nothing decided by your account's defaults, and your named people's tags stay home. Check Flickr for Updates brings your Flickr-side work back as a review sheet you tick. New tonight: Match Flickr Archive finds the photos you uploaded years before TAG Lens existed and links them — matched on your Mac by filename and taken-time agreeing to the minute, ambiguity refused outright, one ⌘Z to unlink — so your old archive joins the loop too (#1749, #2010).
- Point your own local AI at a photo with no location and it'll guess the place — the photo never leaves your Mac, only the guessed name gets looked up, and it writes nothing until you press Use (#817, both tiers now shipped).
- Teach TAG Lens your own field. Import a taxonomy pack — a plain CSV of your terms and their broader words, or a JSON file — and it suggests them like a built-in: tag a Copepod and “Zooplankton, Plankton” come along, so a search for plankton still finds it. Import as many as you like, toggle or remove any, and your terms win a name clash — it even tells you which of yours overrode a built-in. Nothing is sent; it all stays on your Mac (#1899).
- Stories got their room: click a story's card and the memoir opens — your words leading, the photos gathered beneath, and chips linking every story that shares them ('Shelf 2024 · 3 shared', one tap hops over). Rebuilding a memory now has a page (#1108).
- Tell TAG Lens 'Roll 12 was 1987' and every scanned frame still wearing its scan date offers the true year — one assertion, one review, one ⌘Z (#823). And TAG Lens speaks Japanese now — every screen a Japanese speaker actually reads, start to finish: the core surfaces, every settings explanation, every error and toast and count, and all 49 taxonomy pack names (軍装品, 貨幣・古銭…). Your own words are never touched, and a build gate keeps a mistranslation from ever crashing the app (#1035, #1897).
- Film shooters: the roll workbench shipped (#1831). Name a roll (“Roll 12 — Canon AE-1 · Tri-X 400”), assign your scans, and every frame wears an honest “Shot on” row — asserted by you, never forged into the file. Filter to a roll, stamp its tags in ~6 keys, and it all rides your backup file.
- Your scanner can't lie anymore: when the EXIF camera field names a Perfection, CanoScan, Noritsu or friends, TAG Lens says “Scanner”, treats the file date as a scan date, and offers the group date repair built for exactly those photos (#823).
- macOS 27's first-party Photos writes (#1835). Star ratings: landed — TAG Lens already promotes your stars into Photos on the beta OS. Keywords and captions: Apple pulled that half from the latest beta SDK (it still exists under the hood), so the AppleScript bridge keeps the job while we re-check every seed to GA.
- Apple's new on-device model, benchmarked day one: 36% recall on the control corpus — beats a hosted frontier model on our own prompt, 908ms a photo, free, nothing leaves the Mac. It also refused five famous war photographs, which matters for a memoir app and is now a design constraint on the future built-in tier (#1843).
- The AI bake-off, round one: Claude Fable recognized 31 of 44 famous photographs cold (and named the exact Snake River overlook); Haiku delivered correct tags at a fifth of a cent each; free local models still win the plain-tagging axis (#1874). More columns as keys arrive.
- Species by name is on the way. Our own grader caught every AI we tested topping out at “some kind of bird” — never the actual species — so an on-device model that names it to the Latin binomial is coming: opt-in, downloaded once, all on your Mac, nothing sent anywhere. The recognizer seam and the grading axis are built; the model is the last piece (#1137).
- Control photos install themselves — a beta onboarding step that downloads the benchmark album (checksum-verified, consent-first) so every tester shares the same known-answer test bed (#1873)
- Recognized famous photographs import their documented title, photographer, and tags instead of an AI guess (#1872, opt-in, first slice landing)
- Control corpus keeps growing — public-domain benchmark photos that keep every AI honest (#1834)
- Opening the beta up: GitHub Discussions, a public TestFlight link, and the Flickr angle — exported keywords arrive there as tags (#1875)
Recently fixed
- light-leak detection covers mid-edge / sprocket-side wedges, not just corners (#1908)
- light-leak detection wired end-to-end into the roll check (#2053)
- LightLeakDetector — warm-corner-wedge recurrence with daylight-abstain (#2053 core)
- pin the CGContext backing buffer across draw — no held array pointer (rei)
- match Flickr archive across half-/quarter-hour timezones (#2061)
- nonisolated deinit on MemoizedJSONMap — unbreak the -O Release build (#2060)
- make the pinned .tif/.tiff pack images reachable to the bake-off sweep (#2019)
- localize the Applied/Pasted receipts and the remove-dialog surfaces (#2059)
- keep the #1918 failure cause outside the localized toast frame, reconnecting the stranded ja (#2059)
- Flickr inherit-back undo covers what landed, from the confirmed subset (#2058)
- close the two named residue gaps from #2033 (#1904)
- pre-apply confirm gate for pack imports that would override or annex (#1899)
- surface silent root-annexation on pack import (#1899)
- imported packs carry packVersion/category/exampleTerms (#1899)
Known issues (open)
The full tracker is public: github.com/wells01440/taglens/issues. Beta feedback sent through TestFlight lands there too — screenshots welcome. The chatty part happens on the discussion board.