>> So perhaps that's the problem. parseDynamicFlags could perfectly well simply return any un-recognised flags. Indeed, I thought it did just that -- it certainly returns a list of un-consumed arguments. If it doesn't perhaps that's a bug.
I wouldn't call it a bug; you'd need a way to distinguish unrecognized flags from filenames that look like flags, which isn't supported by the current API. Splitting it into a lower level parser and upper level with error checking seems more correct to me, although I'd instead make the lower level take a callback to be invoked on an unknown flag so you could parse more complex options (consider +RTS as an example), with anything unrecognized afterward being flagged as an error.
> parsePluginOption :: [String] -> [String]
> parsePluginOption l@(o:os)
> | -- handle plugin options here
> | -- really this would be a pattern match, not a guard...
> | otherwise -> l