One day in one repo · 2026-04-28 13:14 PT to 14:20 PT

15 commits in 3 minutes 11 seconds, to fix a crash inside code we never wrote.

Most coverage of open source AI in the last day is foundation-model news. This page is the public git log of one MIT-licensed Mac AI agent on 2026-04-28: the github.com/mediar-ai/fazm repository. Eighteen commits, no new release tag, four lines added to the unreleased array of CHANGELOG.json. The interesting fifteen are a single coordinated burst between 14:17:16 PT and 14:20:27 PT that mitigate FAZM-20: an EXC_BAD_ACCESS in NSConcreteMapTable dealloc inside __NSTouchBarFinderSetNeedsUpdateOnMain_block_invoke_2. Fazm contains zero TouchBar code. The bug was firing on customer Macs anyway. Here is what shipped, in order.

M
Matthew Diakonov
10 min read

Anchor fact, verifiable in 30 seconds

The crash had been firing on customer Macs for 30 days. Line 12 of the new extension file says so out loud.

Open Desktop/Sources/Extensions/NSWindow+CrashWorkarounds.swift on github.com/mediar-ai/fazm. Line 12 reads, verbatim: "First seen 2026-03-29; 83 affected users in 30 days; still firing on 2.4.1." The file is 68 lines long and was committed at 2026-04-28 14:18:04 -0700 in commit 08d15b64. It defines two functions, both of which are wired into the rest of the codebase between 14:17:16 PT and 14:20:10 PT.

What every other story about today says

Read three different recaps of open source AI for April 28, 2026 and you land on the same beats: continued momentum on the early-April foundation model wave (Llama 4 Scout on April 2, Qwen 3 72B on April 5, Codestral 2 on April 8), a few Hugging Face trending shifts, maybe a vllm or llama.cpp point release if the writer is paying close attention. None of those are events that happened in the last 24 hours.

The smaller and faster layer of open source AI is invisible in those recaps: the consumer-facing apps that ship on an app cadence rather than a research cadence. The kind that get installed on real Macs and crash for real users. On the day this article was written, that layer did the unglamorous thing the recaps will not. It hunted down a 30-day-old AppKit weak-reference bug, wrote a 68-line defensive extension, and applied it to every NSWindow in the app. In 3 minutes 11 seconds.

How the crash got here

The stack trace was 100% AppKit, QuartzCore, and CoreFoundation frames. Zero Fazm code. The terminal frame on every report was the same: dealloc on an NSConcreteMapTable instance owned by NSTouchBarFinder, dispatched on the main queue from inside a block named __NSTouchBarFinderSetNeedsUpdateOnMain_block_invoke_2.

Fazm has no NSTouchBar code. The team has not written a custom touch bar, has not subscribed to a touch bar update notification, has not so much as imported the relevant headers. AppKit auto- creates a TouchBar object for every NSWindow regardless. The auto-create path keeps weak references to views in an internal map table. Heavy window churn (a floating control bar that resizes, plus pop-out chats that come and go, plus analysis and silence overlays that flicker over the desktop, plus toast panels) is the workload that races the weak-ref bookkeeping on dealloc. The header comment of the new extension file is candid about this: there is nothing wrong with our app; we are sitting in the path of a bug in code Apple ships.

The codebase, by file count, before and after the burst

Desktop/Sources/Extensions/NSWindow+CrashWorkarounds.swift does not exist. Twelve constructed-by-hand NSWindow / NSPanel subclasses live in the codebase, none of them opted out of AppKit's auto touch bar machinery. The crash had been firing for 30 days; reports were arriving from real users on Fazm 2.4.1. CHANGELOG.json's unreleased array had three bullets in it.

  • Zero defensive workarounds applied
  • 83 affected users in the last 30 days
  • Still firing on the latest tagged release (2.4.1)

The shape of the fix

Five steps, in order. Nothing here is novel; the discipline is keeping each step small enough to revert independently if Apple ships an OS-level fix.

Five steps from stack trace to landed mitigation

  1. 1

    Confirm not us

    Stack trace is 100% AppKit, QuartzCore, CoreFoundation. Zero Fazm code in the report.

  2. 2

    Locate the AppKit bug

    NSTouchBarFinder keeps weak refs to views in an NSMapTable. Heavy window churn races the dealloc.

  3. 3

    Pick a small workaround

    Opt out of auto touch bar and window tabbing. Reversible. No UX impact on the Macs Fazm runs on.

  4. 4

    Write one extension

    68 lines, two static functions plus a notification observer for SwiftUI windows the app does not own.

  5. 5

    Apply to every window

    12 explicit call sites, one app-global hook, one changelog bullet. Land them as 15 small commits.

The 68-line extension, on disk

The whole mitigation lives in one file. Two static functions, one notification observer block, two KVC writes. Reproduced verbatim from origin/main below; the only thing trimmed is the doc-comment block at the top, which restates the stack-trace details already covered above.

commit 08d15b64 - Add Desktop/Sources/Extensions/NSWindow+CrashWorkarounds.swift

// Before commit 08d15b64. The file did not exist.
// Heavy window churn would, with some probability per session,
// produce this stack trace ending the process:
//
//   0  libobjc          objc_release
//   1  CoreFoundation   __CFBasicHashRehash
//   2  CoreFoundation   __CFBasicHashDeallocate
//   3  Foundation       -[NSConcreteMapTable dealloc]
//   4  AppKit           __NSTouchBarFinderSetNeedsUpdateOnMain_block_invoke_2
//   5  libdispatch      _dispatch_call_block_and_release
//
// First seen 2026-03-29. 83 affected users in 30 days. Still firing on 2.4.1.
-242% fewer lines

Two details worth noticing. First, the per-window setter goes through KVC: the property automaticallyCustomizesTouchBar is public on NSResponder but Swift does not always surface it as a stored Swift property in older SDKs in some build configurations, so the implementation tests with responds(to:) before doing a setValue. Second, the NotificationCenter observer inside applyAppGlobalCrashWorkarounds is not redundant with the per-window calls; SwiftUI-managed Window scenes the app does not construct itself only get covered through that observer.

83 users

First seen 2026-03-29; 83 affected users in 30 days; still firing on 2.4.1.

NSWindow+CrashWorkarounds.swift, line 12, on origin/main

The 15 commits, in order

Every entry below is a real commit reachable from origin/main on github.com/mediar-ai/fazm. Hashes are seven-character prefixes; full SHAs and diffs are public. Times are commit date in US Pacific. The first three workspace-inheritance commits (13:14:09 to 13:26:33) are not in this table; this is the FAZM-20 burst on its own.

Time PTHashFile touchedNote
14:17:16cb379afbFazmApp.swiftAdd the global call. The extension file does not exist on this commit yet, so main would briefly fail to build between 14:17:16 and 14:18:04.
14:17:336fe6b855DetachedChatWindow.swiftFirst per-window call site. One line added inside the init body.
14:17:50887f2433FloatingControlBarWindow.swiftThe most-instantiated window in the app. The one a user sees every session.
14:18:0408d15b64Extensions/NSWindow+CrashWorkarounds.swiftThe extension itself. 68 lines, two static functions, the notification observer block.
14:18:14b4887588Chat/ClaudeAuthSheet.swiftAuth sheet that hosts the Anthropic OAuth flow.
14:18:30f6a100abChat/PaywallSheet.swiftSubscription paywall window. Surfaces after the third message in the trial.
14:18:472e9dd4a7FloatingControlBar/AnalysisOverlayWindow.swiftTransient panel; one of the windows that never becomes key, so the global notification observer would not catch it.
14:18:583b67dfecFloatingControlBar/SilenceOverlayWindow.swiftSame shape: transient overlay panel for the silence indicator.
14:19:11e0a49b7aSessionRecordingPermissionWindow.swiftFirst-run permission window. Rare per session, but unprotected before this commit.
14:19:173cf0de5fAppManagementSetup.swiftApp Management setup window. Also first-run flow.
14:19:2998f39f0eToastManager.swiftToast panels that float over the desktop. ToastManager line 41 wires the call into the panel constructor.
14:19:347ca33f56BrowserExtensionSetup.swiftBrowser extension setup window for the Chrome companion extension.
14:19:5401e45a31FeedbackView.swiftIn-app feedback window. The window users land in after the Help Center surface was removed in 32c22764 the day before.
14:20:10cb350790FloatingControlBar/PostOnboardingTutorial.swiftPost-onboarding tutorial window. Last per-window call site to land.
14:20:27131e3736CHANGELOG.jsonOne bullet added to the unreleased array: 'Fixed an intermittent crash on macOS that surfaced during heavy floating-bar and pop-out activity.'

Reproduce with git log --pretty="%h %ci %s" --since="2026-04-28 14:17:00" --until="2026-04-28 14:21:00".

What a per-window call site actually looks like

Eleven of the fifteen commits add a single line of code to a single Swift file. The hash changes, the file changes, the line number changes, but the diff has the same shape. Here is the second commit in the burst, 887f2433, applied to the most- instantiated window in the app:

commit 887f2433 - Fix crash by disabling auto touch bar and tabbing

// FloatingControlBarWindow.swift, before commit 887f2433
init(...) {
    // ... configuration ...
    self.delegate = self
    self.minSize = FloatingControlBarWindow.minBarSize
    self.maxSize = FloatingControlBarWindow.maxBarSize

    setupViews()
}
-11% fewer lines

The shape repeats: find the constructor body, add one call to applyCrashWorkarounds() with the FAZM-20 comment, commit, move on. Read git show 887f2433 and the diff is two lines: one added, plus the closing brace context line. Same for 6fe6b855, b4887588, f6a100ab, 2e9dd4a7, 3b67dfec, e0a49b7a, 3cf0de5f, 98f39f0e, 7ca33f56, 01e45a31, cb350790. Eleven near-identical patches. The point of doing them as eleven commits and not one is that git blame on the new line in any one of those windows points to a commit whose message is specific to that window.

Every call site applyCrashWorkarounds touches today

  • Desktop/Sources/FazmApp.swift line 168 (app-global one-shot, plus NotificationCenter observer)
  • Desktop/Sources/FloatingControlBar/FloatingControlBarWindow.swift line 104
  • Desktop/Sources/FloatingControlBar/DetachedChatWindow.swift line 52
  • Desktop/Sources/FloatingControlBar/AnalysisOverlayWindow.swift line 88
  • Desktop/Sources/FloatingControlBar/SilenceOverlayWindow.swift line 52
  • Desktop/Sources/FloatingControlBar/PostOnboardingTutorial.swift line 619
  • Desktop/Sources/Chat/PaywallSheet.swift line 488
  • Desktop/Sources/Chat/ClaudeAuthSheet.swift line 347
  • Desktop/Sources/ToastManager.swift line 41
  • Desktop/Sources/SessionRecordingPermissionWindow.swift line 221
  • Desktop/Sources/BrowserExtensionSetup.swift line 66
  • Desktop/Sources/FeedbackView.swift line 55
  • Desktop/Sources/AppManagementSetup.swift line 60

Why this is the more honest read on open source AI in the last day

Foundation model releases get the press because they are loud, and the loud part is appropriate; a new generation of weights is actually a step change in the field. But the layer of open source AI that gets installed on actual computers, used by actual people, and that has an installer, an icon in the menu bar, and a paywall is the outer ring: the apps, the local inference engines, the IDE plugins, the desktop agents. That ring ships on a dramatically shorter cadence and almost no one writes about it.

Fifteen commits inside three minutes and eleven seconds in a single repo, hunting an AppKit bug that had been crashing 83 customers for 30 days, is what a normal Tuesday afternoon in that ring looks like. The reason this can happen at all is partly that the Mac-side automation reads structure from accessibility APIs (AXUIElement, kAXFocusedWindowAttribute, role and label introspection) instead of pixels, so a Swift bug is the dominant kind of bug to fix. And it is partly that the repo is open, so the diffs are all public and verifiable while the paint is still drying. There is no way to credibly report a shipping log like this if the commit history is private.

If you want to follow what is actually shipping in open source AI on any given day, watch the changelogs and unreleased sections of small consumer-facing repos. The signal-to-noise is significantly better than the hot-take feed. github.com/mediar- ai/fazm is one example of that ring. There are many.

Want to see how a Mac AI agent built on accessibility APIs actually behaves under heavy window churn?

Book a 20-minute call. We will walk through the FAZM-20 stack trace, the 68-line extension that mitigates it, and how to evaluate small open source AI projects on the texture of their commit log rather than star count.

Frequently asked questions

What actually shipped in open source AI on 2026-04-28?

On April 28, 2026, the github.com/mediar-ai/fazm repo (an MIT-licensed Mac AI agent) recorded 18 public commits to main. Three of them, between 13:14:09 PT and 13:26:33 PT, taught the new pop-out chat shortcut to inherit the workspace of the currently focused pop-out instead of resetting to the global default. The other 15, between 14:17:16 PT and 14:20:27 PT, are the FAZM-20 mitigation: a 68-line Swift extension at Desktop/Sources/Extensions/NSWindow+CrashWorkarounds.swift, an app-global call from FazmApp.swift, and 12 per-window call sites. No new release tag was cut today; the four bullets are sitting in the unreleased array of CHANGELOG.json waiting for a 2.5.1 or 2.6.0 cut.

What is FAZM-20 in plain English?

FAZM-20 is the internal ticket for an EXC_BAD_ACCESS crash whose stack trace ends in NSConcreteMapTable dealloc inside __NSTouchBarFinderSetNeedsUpdateOnMain_block_invoke_2. Translation: the macOS app crashed when the operating system was cleaning up a hash table that NSTouchBarFinder uses internally. Fazm has zero NSTouchBar code in the codebase. AppKit auto-creates a TouchBar object for every NSWindow regardless, and the auto-create path keeps weak references to views in an internal NSMapTable. Heavy window churn (floating bar plus pop-outs plus overlays plus toasts) appears to be triggering a weak-reference bookkeeping bug in that map table on dealloc. The header comment of the new extension file says verbatim: 'First seen 2026-03-29; 83 affected users in 30 days; still firing on 2.4.1.'

Why fix something Fazm did not cause?

Because the user does not care whose bug it is. The crash signature is 100% AppKit, QuartzCore, and CoreFoundation frames; zero Fazm code. But the customer-visible result is the app dies. A consumer Mac AI agent that crashes once a session is unusable, and shipping a defensive workaround is faster than waiting for an OS-level fix from Apple. The mitigation is small and reversible: opt every window out of AppKit's auto-touch-bar machinery, disable window tabbing globally, and move on. If Apple ships a fix, the workaround can be deleted in one commit.

Where can I verify the 15-commit window myself?

Clone github.com/mediar-ai/fazm and run: git log --pretty='%h %ci %s' --since='2026-04-28 14:17:00' --until='2026-04-28 14:21:00'. You should see exactly 15 lines, the first being cb379afb at 14:17:16 -0700 (Fix FAZM-20 TouchBar crash by applying global NSWindow workarounds) and the last being 131e3736 at 14:20:27 -0700 (Update changelog with fix for intermittent macOS crash). The new file Desktop/Sources/Extensions/NSWindow+CrashWorkarounds.swift was introduced by commit 08d15b64 at 14:18:04 PT and is 68 lines long. Every line below maps to a public commit hash you can read in under a minute.

What does the 68-line extension actually do?

Two things. First, applyAppGlobalCrashWorkarounds() is called once from FazmApp.swift at line 168. It sets NSWindow.allowsAutomaticWindowTabbing to false and NSApplication.shared.isAutomaticCustomizeTouchBarMenuItemEnabled to false. Then it registers a NotificationCenter observer on NSWindow.didBecomeKeyNotification and didBecomeMainNotification so any window that becomes visible (including SwiftUI-managed windows the app does not construct itself) gets its per-window mitigations applied. Second, applyCrashWorkarounds() is the per-window method. It sets self.tabbingMode = .disallowed and goes through KVC to set automaticallyCustomizesTouchBar to false. It is idempotent and safe to call multiple times.

How many call sites are there in the codebase right now?

Twelve explicit per-window call sites plus one app-global call. The 12 call sites are FloatingControlBarWindow.swift:104, DetachedChatWindow.swift:52, PaywallSheet.swift:488, ClaudeAuthSheet.swift:347, ToastManager.swift:41, SessionRecordingPermissionWindow.swift:221, BrowserExtensionSetup.swift:66, FeedbackView.swift:55, AnalysisOverlayWindow.swift:88, SilenceOverlayWindow.swift:52, PostOnboardingTutorial.swift:619, AppManagementSetup.swift:60. The app-global call is FazmApp.swift:168. SwiftUI windows the app does not construct itself are caught by the NotificationCenter observer registered inside applyAppGlobalCrashWorkarounds. The grep that confirms this is: grep -rn 'applyCrashWorkarounds()' Desktop/Sources/.

Is there a build risk in committing the call sites before the file that defines them?

Yes, briefly. Commit cb379afb at 14:17:16 PT calls NSWindow.applyAppGlobalCrashWorkarounds() from FazmApp.swift. Commit 08d15b64 at 14:18:04 PT introduces Desktop/Sources/Extensions/NSWindow+CrashWorkarounds.swift, which contains the definition. Between those two commit timestamps (48 seconds), main would not compile in isolation. In practice the staged tree compiled cleanly because the file existed locally before the commits were ordered out, but anyone bisecting between cb379afb and 08d15b64 will hit a build failure. A cleaner ordering would have committed the extension file first; the actual ordering is what landed.

Why apply the workaround per-window when the global call already covers everything?

Defense in depth. The app-global path relies on a NotificationCenter observer, which only fires on didBecomeKeyNotification and didBecomeMainNotification. Some windows in the app (panels, transient overlays, child windows that do not become key) never receive those notifications, so the observer would never apply the per-window mitigation to them. The per-window calls cover those paths explicitly. They also document intent: when you read FloatingControlBarWindow.swift line 104 in isolation you can see what mitigation this window has and why, without having to know about a side effect attached to a global notification at app launch.

How does this connect to the accessibility-API approach that fazm uses for screen reading?

Indirectly. Fazm reads the focused window through the macOS accessibility tree (AXUIElement, kAXFocusedWindowAttribute, kAXChildrenAttribute) instead of through screenshots. That choice means the app spawns a lot of NSWindow and NSPanel instances of its own (a floating control bar, a chat pop-out, an analysis overlay, a silence overlay, a toast, a paywall sheet, a feedback window, several first-run windows). Each of those windows is a candidate for the FAZM-20 weak-ref crash. A screenshot-based agent would have a single full-screen overlay and possibly one chat window, which is a much smaller crash surface. The cost of choosing accessibility APIs is more native windows; the benefit is structural reads instead of pixel-level OCR.

What changed in the workspace-inheritance commits earlier in the day?

Three commits between 13:14:09 PT and 13:26:33 PT changed how a new pop-out chat (Cmd-Shift-N) decides which workspace it belongs to. Before: the new pop-out always opened with the global default workspace. Issue: if you were in a chat about workspace A and pressed Cmd-Shift-N to start a fresh thread on the same project, the new window jumped to whatever the default was. After commit 504b7cf0 at 13:14:24 PT (12 lines added to FloatingControlBarWindow.swift), the new pop-out reads the current workspace of the focused pop-out and inherits it. Commit 1c329ac3 added 18 lines to DetachedChatWindow.swift to make detached chat windows accept an inherited workspace. Commit a559da32 at 13:26:33 PT added the unreleased changelog bullet. Three small commits, one customer-visible UX fix.

Will this ship in a tagged release?

Yes. The four entries currently in the unreleased array of CHANGELOG.json (pop-out debounce, paywall stale-response, workspace inheritance, intermittent crash) will be the spine of the next tagged release. Whether that ends up as 2.5.1 (a patch line) or 2.6.0 (a minor) depends on whether anything else lands first that adds visible product surface. The release rule on this repo is that minor bumps gate on visible product changes (a new feature, a restored UI affordance) and patch versions gate on bug fixes only. Everything in the unreleased array right now is a bug fix, so the natural cut would be a patch.

How should I evaluate small open source AI projects on shipping cadence?

Read the unreleased array of CHANGELOG.json before you read the README. It is the part of the release log that shows what the maintainer thinks is wrong with the most recent tagged version, in their own words, before the marketing copy lands. If there is no unreleased section, that is itself information; the project is either shipped via a different convention or the maintainer is not tracking in-flight work in the open. Then look at how often the unreleased array gets emptied into a tagged release; weekly is healthy for a consumer app, monthly is fine for a library, quarterly suggests the project is dormant. Star counts and headline release notes are far weaker signals than the cadence of the unreleased section.