Default Collector Runner
Default CollectorRunner implementation.
Fetches ACTIVE candidates once per run (so already-STALE or PROMOTED propositions are never re-selected), gathers marks from every configured CollectorStrategy, then asks the SweepPolicy what to do with each marked proposition.
Write behavior by entry point:
collect never touches the repository or record store.
run with
dryRun = truesaves an auditable run record but applies no status change and emits no event.run with
dryRun = falseapplies each decision, saves the run record, then emits a PropositionStatusChanged per applied transition.
SweepAction.MergeInto handling: every loser marked into the same survivor in one run is folded on with a single read and save (not one round-trip per loser), and every transition applied afterwards reads the freshest state of its proposition — never the pre-run snapshot — so a survivor just merged into never gets its new evidence clobbered by a later transition reading stale data. If the survivor can't be found, or isn't ACTIVE anymore (e.g. another mark this run already retired it), every loser in that group falls back to a plain retirement instead of folding evidence onto a proposition retrieval will never surface again.
Concurrency: no shared mutable state — each run call works with its own locals, so runs for different contexts are safe in parallel. Two runs for the same context at once aren't corrupting, just wasteful (both read the same ACTIVE set; the second re-applies or skips already-transitioned propositions). Serialize per context at the scheduling layer if that matters (the DefaultDreamLoopOrchestrator that normally drives this already locks per context).
Parameters
Proposition store to read candidates from and write transitions to.
Mark strategies run during the mark phase.
Policy deciding each marked proposition's fate.
Optional audit store; when null, no run record is saved.
Notified after each applied transition; defaults to a no-op.