- go_core_dispatch case 1: tool handler now calls back to plugin via invokeTool
- go_core_dispatch case 2: stage handler sends full StageContext (11 fields)
- New dispatch methods 26-31: Settings.GetCore/SetCore/ListCore/GetPlugin/SetPlugin/ListPlugin
- Remove dlclose (plugin goroutines may still be running after Stop)
- invokeTool/invokeOutput/invokeStage callbacks with proper error handling
- Fix n2 unused variable
- Move FreeCoreAPI from defer in Start() to Stop()
- Call handle.Stop() before freeing resources
- This prevents SIGSEGV from plugins accessing freed CoreAPI memory
- Plugin's Go bridge code is safe (no C memory bugs)
- internal/plugin/cabi/: dlopen + dlsym for plugin_init
- create_core_api(): C struct with dispatch_bridge→go_core_dispatch
- go_core_dispatch routes all 25 SDK methods (RegisterTool, MemoryAPI, etc.)
- dynamic.go: cabiPlugin uses CreateCoreAPI(sdk)→Start(corePtr)
- Each plugin gets a unique ID stored in CoreAPI.ctx
- C functions moved to loader.c to avoid cgo duplicate symbol issues
- New internal/plugin/cabi/ package: dlopen + dlsym loader
- plugindev: generates z_entry.c + z_bridge_gen.go for c-shared builds
- plugindev: replaces -buildmode=plugin with -buildmode=c-shared
- Go bridge uses mock SDK during Start(), core discovers registrations
- PluginAPI: init/start/stop + invoke_tool/stage/output + get_tool_defs/stages/channels
- ha_dispatch: single C function handles all plugin→core calls via method ID
- tryLoadSO: tries C ABI first, falls back to Go plugin.Open
- All example plugins updated (main.go removed, plg.json targets updated)