After a million changes, I think I've got it working.
The fix appears to be to not have a second intents handler target and not try to share the initial one. The code that would've gone inside the second intent definition (the .intentdefinition file and its handler) should instead go inside the Complications target:
In the General tab of the project view:
Main iOS App target has no supported intents listed. There is a Supported Intents section for them but it's empty. If I put the WidgetEventIntent in here, it fails validation.
Widget target does not have any supported intents because there is no section to add them.
WidgetIntentHandler has only the WidgetEventIntent listed.
Watch App target has only the ComplicationEventIntent.
Complications target does not have any supported intents because there is no section to add them.
In target membership:
ComplicationsEntry.swift which uses the ComplicationEventIntent is only in Complications.
ComplicationEventIntent is in Watch App and Complications.
WidgetEntry.swift which uses the WidgetEventIntent is only in Widget.
WidgetEventIntent is in the Main iOS App, Widget and WidgetIntentHandler.
WidgetIntentHandler.swift is only in WidgetIntentHandler.
Since Xcode doesn't seem to like it when you have more than one dynamic intent, regardless of how they're set up or which targets they're in, removing the ComplicationsIntentHandler target and moving its code into the Complications target itself removed the complexity of that extra target.
With this setup I can deploy to the iPhone Simulator and the Watch Simulator, and also to a physical iPhone and Watch (Series 8), and it validates for sending to App Store Connect. (Though, when it gets to App Review, I'm sure it will be rejected because it's different there, too.)
This really shouldn't have taken so long to figure out, but Xcode provides zero help. As you can see from previous error messages Xcode has given me, it tells you there's a problem and its suggested resolution causes another error that cannot be fixed.
At the very least - and the easiest thing for Apple to do here - would be to have a project set up correctly when you choose to create a new project > Watch App with iOS companion app. If this had some sample code in it that had the complications and widgets already present and in the right place, and with the right targets and intents, I could've created a new project and compared it.
Right now, creating such a project merely gives you the Watch App and iOS app targets. There's nothing in there for widgets or complications. Maybe when you add a new widget or complications target it should put them in the right place?
I've been developing for years with Xcode and this has to be the most frustrating thing I've ever experienced with it.