Hmm, I'm not sure I understand your comment about "live after forking". If what I write below misses something important, feel free to clarify or steer the discussion.
I think it's inaccurate to say that ".LRN wants to make changes to OpenACS core that are only applicable for .LRN". A better statement would be that ".LRN needs to know about events that are handled, and should be handled, by the core pages and/or APIs".
Afaik callbacks are pretty widely used and generally considered good design.
I don't think there's much of a risk to OpenACS pages or API calls provided that exceptions are adequately caught and reported. Importantly, none of the solutions we're discussing could cause breakage to vanilla systems that didn't have .LRN installed, or for that matter any other extensions that might need to know about membership changes.
If we had to choose between the two approaches, with the caveat that there are probably other viable ones as well, I think the choice would be between a) leaving core alone, creating .LRN-specific versions of certain core procs and making sure these track the core versions, b) adding some complexity to the core with the expectation that it will reduce the need to track. Approach b) doesn't guarantee that extensions won't break when the core apis change, but it does guarantee that orthogonal changes become available without any extra effort.
As I mentioned before, approach b) is taken in .LRN so we have working code we can mimic.