Architecture and reference documentation for the Metanoia Bible study app.
| Doc | Subagent | Scope |
|---|---|---|
| KIT.md | ui-designer |
Kit module API, component refs, usage patterns |
| SIGNAL_SAFETY.md | code-reviewer |
Signal type-safe layer, DestroyNotify pattern, GTK FFI rules |
| SETTINGS_IMPLEMENTATION.md | test-automator |
Settings panel TDD coverage, network discovery |
| GEMINI.md | build-engineer |
Zig 0.16+ IO/stdlib migration cheatsheet |
| WINDOWS_SETUP.md | deployment-engineer |
MSYS2 + Zig + GTK4 Windows build instructions |
| PACKAGING.md | deployment-engineer |
macOS/Linux/Android release packaging, Homebrew formula |
| MAINTENANCE.md | — | Caching architecture, testing strategy, quick-wins backlog |
| ZIG_DISCOVERIES.md | llm-architect |
Zig versioning, memory management, GTK FFI gotchas |
| AGENTS.md | task-distributor |
Subagent task definitions for doc maintenance |
Extracted all UI components from src/ui/ into a reusable, decoupled library:
- 12 new files under
src/kit/—ffi.zig,widget.zig,theme.zig,signal.zig,root.zig, and 7 component/util files - Zero
@import("ui/...")calls remain inmain.zig— all routing through@import("kit") - Callback pattern replaces
app_stategod-struct coupling: every component takes typed callbacks (SidebarCallbacks,SearchCallbacks,FlowPickerCallbacks) instead of importing application state - Widget wrappers (
kit/widget.zig): 20 type-safe wrappers (Box, Label, Button, Window, Paned, Stack, etc.) withpub fn widget(self)returning the baseWidgettype
Prevents memory corruption from wrong GClosureNotify signatures at compile time:
DestroyNotify = *const fn (gpointer, ?*anyopaque) callconv(.c) voidSignal.connect()andSignal.connectFlags()wrapg_signal_connect_data- Passing a 1-parameter destroy function is now a compile error
G_CONNECT_AFTERflag available viaconnectFlagsfor safe self-freeing- All 6 kit components refactored to use
Signal.connect()— eliminated ~20 rawg_signal_connect_datacalls
@memcpyoverlap →@memmoveinload_chapter_into_study(main.zig:500)- SettingsPanel self-free: window's
destroysignal withG_CONNECT_AFTERfrees the panel struct after GTK cleanup onSaveClickeduse-after-free: capture allocator beforeclose()frees panel- Settings initial value strings: freed after GTK copies them via
gtk_editable_set_text - TTS engine thread races:
g_thread_joininstop()joins running task thread before cleanup, preventing segfault on mutex access after engine freed - TTS pipeline sub-threads: removed
PipeGenasync sub-threading — synchronous lookahead eliminates orphaned thread allocations