See the discussion in T363496: Collapsable sections split the parser cache and T303615: There's no reason to split the ParserCache on wrapclass for the use case/need.
Description
Event Timeline
This is partially done: we have ParserOutput::setFromParserOptions(ParserOptions $po) now which transfers a number of things: wrapper class (T303615), section edit link flag, the collapsible sections flag (T363496) and the preview flag (T341010). The missing piece is to add a list of these in ParserOptions akin to the existing $initialCacheVaryingOptionsHash, $initialLazyOptions, etc lists so that these "only for ParserOutput" options aren't included in the cache key -- right now collapsibleSections and suppressSectionEditLinks are included in the cache key, and all of these are included in ParserOptions::matches() etc.
This is probably easier than it seems, it just requires careful attention & some documentation to explain how things for later maintainers.
My current thinking is that long-term we shouldn't actually need a separate type for this, these will just be options that are not read at all during a normal parse (and thus don't appear in usedOptions) but are read/used during postprocessing, causing the usedOptions for the postprocessed output to include more options than the usedOptions for the canonical output.
ParserOutput::setFromParserOptions() is therefore a small step in the wrong direction, since it is implicitly adding all of these parser options to the usedOptions set for the canonical output.
However in the short term it is useful to keep these options separate. In https://gerrit.wikimedia.org/r/c/mediawiki/core/+/1204727 we added a separate category for these options. Eventually we can ensure they don't appear as "used" until postprocessing, but we can work around methods like ::setFromParserOptions() and a similar method we might add for postprocessing options (T410916) in the interim by making a separate class of options that are ignored unless we are postprocessing.