Change how spies are retrieved. Use a service loader implementation that will also be available for plugins. Introduce a 'foreign agents' metaphor for plugins.
Minor cleanup.
Create the plugins directory if it doesn't exist.2
First attempt at having the app poll the plugins directory to dynamically reload plugins. Class unloading occurs when threadpools are shutdown and the correct hooks are triggered, now just a matter of making sure the correct triggers happen at the correct time.
Move to more of a tell-don't-ask approach when it comes to retrieving information from spies. Replace the spy allocator with an intermediary that will proxy method calls and return values. This is necessary to begin moving toward making sure that no references to CiSpyHandler can leak through to the rest of the app, preventing class and classloader unloading when a plugin is removed.
Have the ForeignAgencies be able to broadcast when they change, so the IntelligenceAgency knows when to tell the PollingSpys to stop their thread, and invalidate its cache of polling spies.